2011-11-05 40 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:就是這樣。公共契約是固定的,因爲你會在編譯時破壞其他的調用者。這不是一個運行時間的改變,儘管(就像添加一個參數一樣),因爲替換是在編譯時處理的。但是請注意,更改默認值不會導致其他調用者進行更新,因爲它都是在編譯時處理的。 (可選/命名參數純粹是一個編譯時間的詭計) –