扩展方法重载

Extension Method overloading

我有这个扩展方法

public static class Extensions
{
     public static void ConsoleWriteLine(this object Value)
     {
         Console.WriteLine(Value);
     }
}

对于整数值我有一点修改

public static void ConsoleWriteLine(this int Value)
{
    Console.WriteLine("Integer: " + Value);
}

我的问题是: 当我写 int x = 1; x.ConsoleWriteLine(); 时,是什么决定在这种情况下进行第二次延期? intobject 也是

what makes the decision to take the second extension in this case?

当编译器有多个有效方法可供选择时,它使用一组重载决议规则来确定它应该绑定到哪个方法。第二个扩展方法与调用签名完全匹配,所以选择它。由于任何其他类型都可以 直接 转换为 object,因此将选择第一个扩展名。其他数值类型 隐式 可转换为 int,但隐式转换不是 "better" 而是直接转换为父 class.

我相信这里的相关规范是 7.5.3.2:

7.5.3.2 Better function member

For the purposes of determining the better function member, a stripped-down argument list A is constructed containing just the argument expressions themselves in the order they appear in the original argument list. Parameter lists for each of the candidate function members are constructed in the following way:

...

Given an argument list A with a set of argument expressions { E1, E2, ..., EN } and two applicable function members MP and MQ with parameter types { P1, P2, ..., PN } and { Q1, Q2, ..., QN }, MP is defined to be a better function member than MQ if

  • for each argument, the implicit conversion from EX to QX is not better than the implicit conversion from EX to PX, and

由于从intint的"conversion"是"better"从intobject的转换,所以int 选择重载。

请注意,这适用于 所有 重载,而不是 just 扩展方法(尽管有不同的规则来打破扩展和非扩展方法)。

根据MSDN

When the compiler encounters a method invocation, it first looks for a match in the type's instance methods. If no match is found, it will search for any extension methods that are defined for the type, and bind to the first extension method that it finds.

编译器从下往上搜索(即从子class到父class,直到到达class层次结构的顶部),所以在这种情况下, 最具体的方法总会获胜。

嗯, 在这种情况下:

public static class Extensions
{
 public static void ConsoleWriteLine(this object Value)
 {
     Console.WriteLine(Value);
 }
}

您正在为对象编写扩展方法。 参见:

this object Value

在您的其他扩展方法中,您正在为整数编写扩展。

public static void ConsoleWriteLine(this int Value)
{
   Console.WriteLine("Integer: " + Value);
}

因为

this int Value

所以,每次你声明一个 Integer 时,都会调用这个扩展方法,因为这是一个针对整数而不是对象的方法。