gpt4 book ai didi

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

转载 作者:IT王子 更新时间:2023-10-29 04:11:33 25 4
gpt4 key购买 nike

我知道 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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com