带默认参数值的c#方法没有参数会产生过载?

Eri*_*ndi 5 c#

最近,我想在扩展方法中添加一个可选参数.原始方法看起来像这样:

public static class Extensions {
    public static bool Foo(this IFoo target) {
        target.DoIt(true);
    }
}
Run Code Online (Sandbox Code Playgroud)

这显然是一个简化版本,但让我们继续.

我做的是:

public static class Extensions {
    public static bool Foo(this IFoo target, bool flag = true) {
        target.DoIt(flag);
    }
}
Run Code Online (Sandbox Code Playgroud)

我所做的就是引入一个带有默认值的可选参数,对吧?我期待的是编译器生成重载方法,没有标志.这部分发生了.我重新编译的任何代码都能够编译和执行而没有任何问题,即使没有像这样的参数:

...
IFoo foo = new FooBar();
foo.Foo();
...
Run Code Online (Sandbox Code Playgroud)

但是,任何针对以前版本的Foo()构建的代码都不起作用,抛出以下异常:

Unhandled Exception: System.MissingMethodException: Method not found: 'Boolean Models.Class1.Foo()'.
at DefaultParamsTests.Program.Main(String[] args)
Run Code Online (Sandbox Code Playgroud)

这对我们来说显然是一个问题,因为我们有一个公共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);
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,Resharper建议我可以为方法foo引入一个可选参数.

resharper引入可选参数

如果我遵循重构它基本上做了我上面显示的.但是,这对现有代码不起作用.

resharper重构

我使用Reflector和dotPeek查看了生成的IL.两者都没有显示过载的产生.

我错过了什么?

And*_*ker 5

在默认参数的情况下,实际调用站点被重写以使用默认值。这意味着根本不会生成重载,您的调用代码已被修改!

public void fun(int x = 3) { }

// in another file
fun();   // compiler re-writes to fun(3);
fun(7);  // fun(7) as expected

// actual code generated by the c# compiler
fun(3);
fun(7);
Run Code Online (Sandbox Code Playgroud)

如果在 C# 中使用可选参数,则需要在function更改时重新编译所有调用方。出于这个原因,强烈建议不要将这些类型的方法放在公共接口上(例如,由其他代码调用)。在您自己的链接项目中使用它们很好,因为它们应该同时编译

  • @maxwellb 那是同样的问题。编译器为您重新编写了调用,因此您必须重新编译。如果它是内部代码,仅在您的项目中使用(并且具有适当的依赖项),那么它们在某些情况下是一个很好的节省时间的方法。除了“内部”类之外,我总是使用重载,以防有人滥用我写的内容:D (2认同)