c# - 用重载替换一个可选参数是一个破坏性的变化吗?

标签 c# .net vb.net optional-parameters

我知道 adding an optional parameter in a library method is a breaking change ,

void Foo(int x)             // OLD
void Foo(int x, int y = 5)  // NEW

因为在编译后的代码中,新版本被视为 Foo(int, int)Foo(0)(源代码)的每次调用都被编译器翻译成Foo(0, 5)(编译代码)。因此,使用 Foo(0) 编译调用的旧客户端找不到合适的方法。


另一个方向呢?

void Foo(int x, int y = 5) { ... }    // OLD

void Foo(int x)        { Foo(x, 5); } // NEW
void Foo(int x, int y) { ... }        // NEW

Foo(0)(源代码)仍然可以编译,Foo(0, 5)(编译后的代码)仍然可以找到合适的重载,因此,理论上,这应该有效。

它在实践中是否有效,即这种情况是否得到 .NET 运行时和 C#/VB 编译器的“官方支持”?还是对带有可选参数的方法的调用以某种方式被“标记”,导致当可选参数被重载替换时它们失败?


编辑:为了澄清,我问的是二进制兼容性:Is it possible to replace library.dll (old) with library.dll (new ) 无需重新编译 projectUsingLibrary.exe

最佳答案

我认为这是一个很好的问题,所以这是我的看法。

使用执行此操作的快速客户端:

        c1.Foo(1);
        c1.Foo(1, 2);

当使用可选参数时,客户端 IL 如下所示:

    IL_0000: nop
IL_0001: newobj instance void [ClassLibrary1]ClassLibrary1.Class1::.ctor()
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: ldc.i4.1
IL_0009: ldc.i4.5
IL_000a: callvirt instance void [ClassLibrary1]ClassLibrary1.Class1::Foo(int32, int32)
IL_000f: nop
IL_0010: ldloc.0
IL_0011: ldc.i4.1
IL_0012: ldc.i4.2
IL_0013: callvirt instance void [ClassLibrary1]ClassLibrary1.Class1::Foo(int32, int32)
IL_0018: nop
IL_0019: ret

当使用重载时,它看起来像:

    IL_0000: nop
IL_0001: newobj instance void [ClassLibrary2]ClassLibrary2.Class2::.ctor()
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: ldc.i4.1
IL_0009: callvirt instance void [ClassLibrary2]ClassLibrary2.Class2::Foo(int32)
IL_000e: nop
IL_000f: ldloc.0
IL_0010: ldc.i4.1
IL_0011: ldc.i4.2
IL_0012: callvirt instance void [ClassLibrary2]ClassLibrary2.Class2::Foo(int32, int32)
IL_0017: nop
IL_0018: ret

因此,如果您将实现从可选更改为重载,但让客户端保持原样,它将有效地为您添加默认参数,并始终调用具有两个参数的函数,这可能会也可能会不是期望的行为。

关于c# - 用重载替换一个可选参数是一个破坏性的变化吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12670735/

相关文章:

c# - 自动属性验证

.net - 返回不同数据类型的函数

c# - 使用数组和 redim 保护器关键字将 VB 代码转换为 C#

arrays - 检查属性是否是数组

c# - 为什么此事件日志的 EntryWritten 事件永远不会触发?

c# - 从 MDF 数据库中删除记录

c# - 如何测试 DataBound 中的交替行

c# - 如何安装 Microsoft.Silverlight.Testing?

c# - 将 Dictionary<int, List<string>> 分配给空的新声明字典

c# - C# 打印中的换页