2011-11-05 66 views
9

我读了几篇文章,说在C#3.0中引入命名参数时,参数的名称现在是公共合约的一部分。 这是真的吗?它是什么意思?我运行了一个简单的测试,并且在MyLib.dll中更改了一个参数名称并没有打破MyApp.exe,它使用带有原始名称的命名参数调用该方法,我认为是因为C#编译器在编译时确实重载了解析, IL对参数名称一无所知。这是反汇编代码看起来反光什么:C#中的参数名称更改是否为运行时间更改?

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(); 
} 
+0

是的,你明白这一点,它不会打破。面对突破的情况很难,我不能随便提出一个迟到的绑定方案。 –

回答

19

我读了几篇文章,说在C#3.0中引入命名参数时,参数的名称现在是公共合约的一部分。这是真的吗?它究竟意味着什么?

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

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

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

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

C#不是唯一的.NET语言,不远。当您更改某种类型的公开可见表面的部分内容时,可能会以语言打破的程序。有或没有功能的C#不会改变这一事实。

11

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

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

调用者可以编写使用它,像这样的应用程序:

Foo(a: true); 

如果然后更改方法:

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

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

+0

斑点,清澈透明。岩石 –

+1

是的,我明白这是一个编译时间突变。 –

+0

@MaxToro:就是这样。公共契约是固定的,因为你会在编译时破坏其他的调用者。这不是一个运行时间的改变,尽管(就像添加一个参数一样),因为替换是在编译时处理的。但是请注意,更改默认值不会导致其他调用者进行更新,因为它都是在编译时处理的。 (可选/命名参数纯粹是一个编译时间的诡计) –