具有默认参数值的c#方法不会生成没有参数的重载?

标签 c#

最近,我想为扩展方法添加一个可选参数。原始方法如下所示:

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)

这对我们来说显然是个问题,因为我们确实有一个公共(public) 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 引入一个可选参数。

resharper introduce optional parameter

如果我确实遵循重构,它基本上会执行我上面显示的内容。但是,这不适用于现有代码。

resharper refactored

我查看了使用 Reflector 和 dotPeek 生成的 IL。也没有显示过载的产生。

我错过了什么?

最佳答案

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

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);

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

关于具有默认参数值的c#方法不会生成没有参数的重载?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28184423/

相关文章:

c# - 是否可以将 Windows 窗体中的表格用作矩阵?

c# - VS 2012 的 LINQ to SQL 调试可视化工具?

c# - 从pkcs#11 token 或智能卡访问证书和私钥

c# - 创建指向目录的符号链接(symbolic link)的问题

c# - 具有多个计数的 Linq 查询

c# - WPF文本框字符串格式忽略小数

c# - 如何将委托(delegate)原型(prototype)传递给方法?

c# - EF Core - 在一个请求中添加/更新实体和添加/更新/删除子实体

c# - 我想打开一个excel文件并等待用户编辑并保存它

c# - 将部分类与普通类相结合