添加可选参数是否会更改方法签名,是否会触发方法缺少exception?

我们有几个引用库程序集的项目让我们调用“myUtil”,现在是几个项目中引用的方法之一,

GetData(int p1, string p2, object p3, bool p4 = false); 

现在,如果我改变上述方法,

 GetData(int p1, string p2, object p3, bool p4 = false, bool p5 = false); 

我是否必须将“myUtil.dll”程序集更新为引用它的项目?

没有引用它我得到这个错误,这确实有意义,并在我更新引用时消失, 但我不能有效查找引用,它说你必须更新引用

System.MissingMethodException:找不到方法:’Void GetData(….

必须更新所有引用。

可选参数只是语法糖。

当你有这个:

 GetData(int p1, string p2, object p3, bool p4 = false); 

并称之为:

 GetData(1, "p2", obj); 

编译器执行此操作:

 GetData(1, "p2", obj, false); 

您需要重新编译并重新部署引用它的所有程序集/项目。

您不需要删除并重新添加引用,但您需要重建所有针对DLL编译的项目。 添加可选参数是源兼容但不是二进制兼容的更改,因为编译器在调用站点发出不同的IL,以包含正常的默认值 – 无论可选参数是否,IL中的调用本身看起来都相同省略与否。

例如,请考虑以下代码:

 class Test { static void Main() { Foo(3); Foo(); } static void Foo(int x = 5) { } } 

IL for Main看起来像这样:

  .method private hidebysig static void Main() cil managed { .entrypoint // Code size 16 (0x10) .maxstack 8 IL_0000: nop IL_0001: ldc.i4.3 IL_0002: call void Test::Foo(int32) IL_0007: nop IL_0008: ldc.i4.5 IL_0009: call void Test::Foo(int32) IL_000e: nop IL_000f: ret } // end of method Test::Main 

如您所见,常量5 Main方法中加载并作为参数传递,就像显式为3一样。 在assembly边界上发生同样的事情。

相同的规则也适用于更改常量的值,以及更改可选参数的默认值 – 所有这些都需要客户端重建。

如果停止使用可选参数并使用方法重载,则可以保持兼容性:

 public void GetData(int p1, string p2, object p3, bool p4 = false, bool p5 = false) { //Do something } 

 public void GetData(int p1, string p2, object p3) { GetData(p1, p2, p3, false); } public void GetData(int p1, string p2, object p3, bool p4) { GetData(p1, p2, p3, p4, false); } public void GetData(int p1, string p2, object p3, bool p4, bool p5) { //Do something } 

但是,除非重新编译所有项目,否则这不会反映默认值的更改。 例如,任何旧的GetData(1, "2", null)将始终调用新的GetData(1, "2", null, false)即使您更改

 public void GetData(int p1, string p2, object p3) { GetData(p1, p2, p3, false); } 

 public void GetData(int p1, string p2, object p3) { GetData(p1, p2, p3, true); }