【问题标题】:Is a parameter name change in C# a runtime breaking change?C# 中的参数名称更改是运行时的重大更改吗?
【发布时间】:2011-11-05 01:03:52
【问题描述】:

我读过几篇文章说,随着在 C# 3.0 中引入命名参数,参数名称现在成为公共合同的一部分。 这是真的吗,这到底是什么意思?我运行了一个简单的测试,更改 MyLib.dll 中的参数名称并没有破坏 MyApp.exe,它使用具有原始名称的命名参数调用该方法,我认为是因为 C# 编译器在编译时做了重载解析,而生成的 IL 对参数名称一无所知。这是反汇编代码在 Reflector 上的样子:

private static void Main()
{
    bool CS$0$0000 = true;
    Class1.DoSomething(CS$0$0000);
    Console.ReadKey();
}

...这是原始源代码:

static void Main() {

    MyLib.Class1.DoSomething(a: true);

    Console.ReadKey();
}

【问题讨论】:

  • 是的,你明白这一点,它并没有破坏。想出一个破坏的场景很困难,我不能轻易想出一个后期绑定的场景。

标签: c# .net


【解决方案1】:

我读过几篇文章说,随着在 C# 3.0 中引入命名参数,参数名称现在成为公共合同的一部分。这是真的吗,具体是什么意思?

参数名称确实是公共合同的一部分,但该语句包含两个错误。

最明显的错误是命名参数是在 C# 4.0 中引入的,而不是 C# 3.0。

但更微妙的错误更为重要。在 C# 4.0 中引入的命名参数现在没有使参数名称成为方法的公共合同的一部分。 参数名称​​始终是公共合同的一部分,因为 C# 以外的语言具有命名参数功能。 特别是,VB 一直支持命名参数。

因此,更改库中参数的名称​​始终是 VB 重新编译的重大更改。现在它也是 C# 重新编译的一个重大变化,但这并不意味着它以前是安全的,现在它是危险的。这总是很危险的。

C# 不是唯一的 .NET 语言,到目前为止还不是。当您更改类型的公开可见表面的一部分时,您可能会破坏所有语言的程序。 C# 有或没有一个特性并不会改变这个事实。

【讨论】:

    【解决方案2】:

    问题是,假设你有一个像这样的公共 API:

    public void Foo(bool a = false)
    {
        //....
    

    调用者可以编写一个使用它的应用程序,如下所示:

    Foo(a: true);
    

    如果您随后将方法更改为:

    public void Foo(bool aBetterName = false)
    {
        //....
    

    现在,突然之间,调用者的代码将不再编译,因为编译器(一旦更新到您的新库)将不再看到名为 a 的参数。

    【讨论】:

    • 是的,我知道这是编译时的重大更改。
    • @MaxToro:就是这样。公共合约是固定的,因为你会破坏(在编译时)其他调用者。不过,这不是运行时的重大更改(就像添加参数一样),因为替换都是在编译时处理的。但是请注意,更改默认值不会导致其他调用者更新,因为它都是在编译时处理的。 (可选/命名参数纯粹是编译时技巧)
    猜你喜欢
    • 1970-01-01
    • 2018-08-16
    • 1970-01-01
    • 2018-07-09
    • 1970-01-01
    • 1970-01-01
    • 2022-01-18
    • 2016-03-11
    • 1970-01-01
    相关资源
    最近更新 更多