可选参数:如果存在重载覆盖,则优先顺序相反
optional parameter: reversed precedence if override of overload exists
我想知道以下行为:
public class A {
public virtual void Do() { Console.WriteLine("A"); }
}
public class B : A {
public override void Do() { Console.WriteLine("B override"); }
public void Do(int value = 0) { Console.WriteLine("B overload"); }
}
class Program {
public static void Main() {
new B().Do(); // ---> Console: "B overload"
}
}
我希望具有确切签名的重载优先于另一个具有可选参数的重载:我希望在控制台中显示 "B override"。相反,程序将 "B overload" 写入控制台。
连resharper都失败掉进陷阱:
... Resharper说带有可选参数的重载被带有精确签名的重载隐藏了,但实际上恰恰相反
现在,如果您删除继承,那么它会按预期运行并且 resharper 警告是合法的:
public class B {
public virtual void Do() { Console.WriteLine("B override"); }
public void Do(int value = 0) { Console.WriteLine("B overload"); }
}
class Program {
public static void Main() {
new B().Do(); // ---> Console: "B override"
}
}
所以问题是:解释这个观察的优先规则是什么?为什么具有精确签名的重载不优先于另一个具有可选参数的重载,以防具有精确参数的重载覆盖基本实现?
Why an overload with exact signature doesn't have precedence over another overload with optional parameters in case that the overload with exact parameters overrides a base implementation?
基本上这是遵循规范规则的编译器,尽管在这种情况下它们令人惊讶。 (第 7.6.5.1 节是 C# 5 规范的相关部分。)
编译器首先查看 "deepest" 类型 - 即具有目标编译时类型的类型(在本例中为 B
)并尝试找到适用的函数成员 忽略任何重写基类中声明的方法 class:
The set of candidate methods is reduced to contain only methods from the most derived types: For each method C.F in the set, where C is the type in which the method F is declared, all methods declared in a base type of C are removed from the set.
和:
The intuitive effect of the resolution rules described above is as follows: To locate the particular method invoked by a method invocation, start with the type indicated by the method invocation and proceed up the inheritance chain until at least one applicable, accessible, non-override method declaration is found. Then perform type inference and overload resolution on the set of applicable, accessible, non-override methods declared in that type and invoke the method thus selected. If no method was found, try instead to process the invocation as an extension method invocation.
因此在您的情况下,编译器 仅 考虑新引入的方法,发现它适用(使用默认参数值)并停止搜索。 (即它不查看在 base classes 中声明的方法)。那时,候选函数成员集只有一个条目,因此此时没有真正的重载决议要执行。
我有一个 article on overloading 显示了这种情况,它没有使用可选参数而是使用了不同的参数类型 - 请参阅 "Inheritance" 部分。
我想知道以下行为:
public class A {
public virtual void Do() { Console.WriteLine("A"); }
}
public class B : A {
public override void Do() { Console.WriteLine("B override"); }
public void Do(int value = 0) { Console.WriteLine("B overload"); }
}
class Program {
public static void Main() {
new B().Do(); // ---> Console: "B overload"
}
}
我希望具有确切签名的重载优先于另一个具有可选参数的重载:我希望在控制台中显示 "B override"。相反,程序将 "B overload" 写入控制台。
连resharper都失败掉进陷阱:
... Resharper说带有可选参数的重载被带有精确签名的重载隐藏了,但实际上恰恰相反
现在,如果您删除继承,那么它会按预期运行并且 resharper 警告是合法的:
public class B {
public virtual void Do() { Console.WriteLine("B override"); }
public void Do(int value = 0) { Console.WriteLine("B overload"); }
}
class Program {
public static void Main() {
new B().Do(); // ---> Console: "B override"
}
}
所以问题是:解释这个观察的优先规则是什么?为什么具有精确签名的重载不优先于另一个具有可选参数的重载,以防具有精确参数的重载覆盖基本实现?
Why an overload with exact signature doesn't have precedence over another overload with optional parameters in case that the overload with exact parameters overrides a base implementation?
基本上这是遵循规范规则的编译器,尽管在这种情况下它们令人惊讶。 (第 7.6.5.1 节是 C# 5 规范的相关部分。)
编译器首先查看 "deepest" 类型 - 即具有目标编译时类型的类型(在本例中为 B
)并尝试找到适用的函数成员 忽略任何重写基类中声明的方法 class:
The set of candidate methods is reduced to contain only methods from the most derived types: For each method C.F in the set, where C is the type in which the method F is declared, all methods declared in a base type of C are removed from the set.
和:
The intuitive effect of the resolution rules described above is as follows: To locate the particular method invoked by a method invocation, start with the type indicated by the method invocation and proceed up the inheritance chain until at least one applicable, accessible, non-override method declaration is found. Then perform type inference and overload resolution on the set of applicable, accessible, non-override methods declared in that type and invoke the method thus selected. If no method was found, try instead to process the invocation as an extension method invocation.
因此在您的情况下,编译器 仅 考虑新引入的方法,发现它适用(使用默认参数值)并停止搜索。 (即它不查看在 base classes 中声明的方法)。那时,候选函数成员集只有一个条目,因此此时没有真正的重载决议要执行。
我有一个 article on overloading 显示了这种情况,它没有使用可选参数而是使用了不同的参数类型 - 请参阅 "Inheritance" 部分。