Optional argument in interface without default value
令我惊讶的是,C使用值作为接口的可选方法参数,而不是实现此接口的类的参数。例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | using System; public class Program { private static IMyInterface instance; public static void Main() { instance = new MyClass(); instance.PrintOpt(); ((MyClass)instance).PrintOpt(); } } public interface IMyInterface { void PrintOpt(bool opt = false); } public class MyClass : IMyInterface { public void PrintOpt(bool opt = true) { Console.WriteLine($"Value of optional argument is {opt}"); } } |
产生输出:
Value of optional argument is False
Value of optional argument is True
号
我的问题是-可以在接口中定义一个没有默认值或"可重写"的可选参数,所以对保存在接口类型变量中的实例调用方法时,会使用在实现此接口的类中定义的可选值?
如果您理解了可选参数是如何在内部处理的,这并不奇怪:它们是在编译期间内联的。
换句话说,在调用方法的地方,任何可选参数都由编译器传递——如果您调用的是接口方法,编译器不知道有一个具有不同可选参数的实现。这样的代码最明显的区别是:
1 2 3 4 5 | IMyInterface interface = new MyClass(); MyClass theClass = (MyClass)interface; interface.PrintOpt(); // false theClass.PrintOpt(); // true |
编译成这个(翻译回c):
1 2 | interface.PrintOpt(false); theClass.PrintOpt(true); |
号
在IL代码中,"default"参数不再是"default"——它们只是另一个显式传递的参数。
如果要使用可重写的可选参数,只需使用方法重载。或者更好的方法是,使用不代表任何内容的默认值(例如,
1 2 | comInterface.MyMethod(TheActualArgumentICareAbout, Type.Missing, Type.Missing, Type.Missing, Type.Missing, ...); |
现在你可以做了
1 | comInterface.MyMethod(argument, anotherSuperUseful: true); |
。
这种区别是一个大问题——它还意味着您不应该更改任何公共方法的默认参数。任何未经重新编译而使用您的库的用户仍将使用旧的默认值。它类似于处理