使参数非可选是否为向后二进制兼容的更改

本文关键字:二进制 参数 是否 | 更新日期: 2023-09-27 17:51:12

我正在向函数添加一个新的可选参数,我想保持二进制向后兼容性。旧的API是:

public void Foo(string message, object data = null) { ... }

新的API是:

// maintained for backwards compat
public void Foo(string message, object data) { Foo(message, data, null); }
public void Foo(string message, object data = null, TimeSpan? time = null) { ... }

我需要删除旧API中数据的默认值的原因是,否则对Foo("a")的调用是模糊的。我不想在新方法中要求数据参数,因为一个常见的用例是做Foo(message, time: time)。同样,我也不想改变参数的顺序,因为实际代码中的顺序很有意义。

二进制是否向后兼容(忽略可能访问ParameterInfo.DefaultValue的反射)?我的想法是,由于可选参数是在编译时处理的,因此不传递参数和在IL中传递参数之间没有区别。例如,以下LinqPad代码:

void Main()
{
    A(0);
    A();
}
// Define other methods and classes here
public int A(int a = 0) { return a; }

为Main()生成以下IL:

IL_0001:  ldarg.0     
IL_0002:  ldc.i4.0    
IL_0003:  call        UserQuery.A
IL_0008:  pop         
IL_0009:  ldarg.0     
IL_000A:  ldc.i4.0    
IL_000B:  call        UserQuery.A

因此,看起来没有区别。但是,我不确定二进制兼容性究竟包含什么。例如,编译后的代码是否保留了一些对UserQuery的预期签名的引用。如果它是在另一个程序集中定义的?

使参数非可选是否为向后二进制兼容的更改

是;这是向后兼容的