【发布时间】:2015-03-26 21:22:45
【问题描述】:
最近,我想在扩展方法中添加一个可选参数。原来的方法是这样的:
public static class Extensions {
public static bool Foo(this IFoo target) {
target.DoIt(true);
}
}
这显然是一个简化版本,但让我们从那个开始。
我所做的是:
public static class Extensions {
public static bool Foo(this IFoo target, bool flag = true) {
target.DoIt(flag);
}
}
我所做的只是引入一个带有默认值的可选参数,对吧?我期待的是编译器生成重载方法,没有标志。 这部分发生了。我重新编译的任何代码都能够毫无问题地编译和执行,即使没有这样的参数:
...
IFoo foo = new FooBar();
foo.Foo();
...
但是,针对以前版本的 Foo() 构建的任何代码都不起作用,引发以下异常:
Unhandled Exception: System.MissingMethodException: Method not found: 'Boolean Models.Class1.Foo()'.
at DefaultParamsTests.Program.Main(String[] args)
这对我们来说显然是个问题,因为我们确实有一个供客户使用的公共 API,这将是一个重大变化。
解决办法是显式创建一个重载:
public static class Extensions {
public static bool Foo(this IFoo target) {
target.DoIt(true);
}
public static bool Foo(this IFoo target, bool ) {
target.DoIt(true);
}
}
不过,Resharper 确实建议我可以为方法 foo 引入一个可选参数。
如果我确实遵循了重构,它基本上就是我上面展示的。但是,这不适用于现有代码。
我已经使用 Reflector 和 dotPeek 查看了生成的 IL。两者都没有显示过载的产生。
我错过了什么?
【问题讨论】:
-
是什么让您相信编译器会为单个声明生成两个方法重载?
-
我想你已经回答了你的问题。你可以只添加方法而忽略Resharper的引入可选参数的建议吗?
-
@gknicker,显然,在某处创建了过载。否则,默认参数将不起作用。正如回答问题的两个人所指出的那样,我假设它是在错误的地方生成的。默认值由编译器在调用站点而不是声明站点注入。
-
@maxwellb,是的,这就是我最终“修复”它的方式。我只是好奇而已。你和安德鲁在回答这个问题上做得很好。我什至最终用 dotPeek 确认了这一点。是的,默认值是在调用站点注入的。
-
首先,这个问题写得真好。很清楚,而且有很多好的代码sn-ps。 SO现在需要更多这些。我应该提一下,我关闭了很多 resharper 的建议。有些损害可读性,有些只适用于 1/2 的时间。这是一个我很确定我关掉了
标签: c#