方法签名的定义是什么?

9 浏览
0 Comments

方法签名的定义是什么?

方法签名(或方法的签名)的正确定义是什么?

在谷歌上,我找到了各种定义:

它是方法名称和参数列表的组合

这是否意味着方法签名 = 方法名称 + 参数列表?那么我看不出"方法"和"方法签名"之间有什么区别。

如果我有一个方法:

public void Foo(int x, int y) { ... }

我的方法签名会是以下哪一个,或者都不是?

  • Foo
  • Foo(int, int)
  • Foo(int x, int y)
  • Foo(34, 78)

如果有人问我这个方法的方法签名是什么,我该如何回答?

0
0 Comments

方法签名的定义是指方法的名称、泛型数量、形式参数数量、形式参数类型和种类,但不包括返回类型和"params"修饰符。

尽管这是正确的,但是这里有一些微妙之处。C#语言定义方法签名的方式与CLR定义方法签名的方式不同,这可能会导致在C#和其他语言之间进行互操作时出现一些有趣的问题。

对于CLR来说,方法签名由方法名称、泛型数量、形式参数数量、形式参数类型和种类以及返回类型组成。因此,这是第一个不同之处;CLR考虑了返回类型。

CLR还不认为"out"和"ref"是不同的形式参数种类;而C#认为是。

CLR还有一个有趣的特性,称为"optional and required type modifiers",通常称为"modopts"和"modreqs"。可以使用另一种类型对方法签名中的类型进行注释,该类型告诉您有关"主"类型的信息。例如,在C++中,以下两个签名是不同的:

void M(C const & x);
void M(C & x);

这两个签名都定义了一个接受"type reference to C"类型的参数的方法M。但是因为第一个是一个const引用,而第二个不是,所以C++语言认为这些是不同的签名。CLR通过允许C++/CIL编译器在形式参数类型上发出一个特殊的"this is const"类型的modopt来实现这一点。

在C#中没有办法读取或设置mod,但是C#编译器仍然知道它们并且会以某种方式予以支持。例如,如果您在C++/CIL中声明了一个公共虚方法:

void V(C const * x)

并且在C#中的派生类中覆盖它,C#编译器不会强制执行const正确性;C#编译器不知道const modopt的含义。但是C#编译器将确保覆盖方法在元数据中带有modopt。这是必需的,因为CLR要求覆盖和被覆盖方法的签名匹配;编译器必须遵守CLR规则进行签名匹配,而不是C#规则。

这些mod除了const之外还用于其他方面吗?

是的。"const"是一个modopt,它是可选的,因为如果您不理解它,不会有任何损害。const正确性不是一种好行为的保证,而是一种意图的说明。"volatile"是一个modreq,它是必需的,因为如果您不理解它,可能会破坏某些东西。"volatile"是一个保证,即对该事物的每次访问都将具有获取和释放语义;如果您不理解这一点,那么就不能触碰这个volatile事物。

还用于其他方面吗?是的,参见ikvm,我最近在那里了解到这些修饰符:weblog.ikvm.net/…

"CLR考虑返回类型。"我猜这与Java相同,即如果更改返回值,可能会破坏向后兼容性,例如从void更改为<some value>:您不会得到编译错误,但是在运行时可能找不到该方法(如果我们正在处理多个项目,并且不是所有项目都重新编译)。

0
0 Comments

方法签名的定义是指方法的名称以及每个形式参数的类型和种类(值、引用或输出),按从左到右的顺序考虑。方法签名特别不包括返回类型,也不包括可能为最右边的参数指定的params修饰符。

重要的是,方法的返回类型不属于其签名。因此,您不能只通过返回类型来重载方法!

根据您在MSDN上的参考:签名包括方法的输出,但您说不包括返回类型。所以签名包括返回值(如输出),但不包括返回类型?

我认为您混淆了返回值和输出参数。返回类型不属于签名。但是输出参数确实属于签名(请参阅输出参数修饰符,msdn.microsoft.com/en-us/library/ee332485.aspx)

您甚至不能只通过返回类型来区分方法,因为它们之间会产生歧义。编译器不会接受这种情况。

根据MSDN,返回类型是方法签名的一部分,但您正确地指出您不能仅通过返回类型进行重载。"方法是通过指定访问级别(如public或private)、可选修饰符(如abstract或sealed)、返回值、方法名称和任何方法参数来在类、结构或接口中声明的。这些部分一起构成方法的签名。"

0
0 Comments

方法签名是编译器用来识别方法的一组属性。这些属性包括方法名、参数个数、参数类型和参数顺序。举个例子,不同的方法签名如下:

Foo()
Foo(int)
Foo(String)
Foo(int, string)
Foo(string, int)

这些方法都是不同的,当你在代码中调用它们时,编译器可以根据方法签名推断出你想要执行的方法。在模块化编程中,不要忘记方法的作用域。

总是喜欢这样简单的答案。谢谢!

0