考慮在類庫下面的代碼省略參數不破的應用:庫更改委託簽名使用它
public class Service
{
public delegate string Formatter(string s1, string s2);
public void Print(Formatter f)
{
Console.WriteLine(f("a", "b"));
}
}
下面是一個使用它的控制檯應用程序:
static void Main(string[] args)
{
s = new Service();
s.Print(Concat);
}
static string Concat(string s1, string s2)
{
return string.Format("{0}-{1}", s1, s2);
}
到目前爲止,它打印出「ab」,就像人們所期望的那樣。
現在,我改變類庫如下:
public class Service
{
public delegate string Formatter(string s1);
public void Print(Formatter f)
{
Console.WriteLine(f("a"));
}
}
即我從委託中刪除了一個參數。我只編譯類庫和覆蓋DLL坐在旁邊的控制檯應用程序(控制檯應用程序是不重新編譯)。我期望這是庫中的重大變化,如果我執行應用程序,它會發現不匹配,導致一些運行時異常。
相比之下,當我運行該應用程序時,根本沒有例外,我得到驚人的輸出「-a」。當我調試時,我可以看到Concat方法(帶有2個參數)被調用,下面的調用堆棧級別顯示Print調用f(「a」)(一個參數),任何地方都沒有錯誤指示。最有趣的是,Concat中的s1爲空,s2爲「a」。
我還與到簽名不同的變化(添加參數,改變參數類型)大多具有相同的結果發揮各地。當我將s2的類型從字符串更改爲int時,我得到一個異常,但不是當Concat方法被調用時,而是當它試圖調用string.Format時。
我使用.NET框架的目標4.5.1和3.5,x86和x64試了一下。
任何人都可以回答這是否是預期的行爲或錯誤?這對我來說很危險。
如果添加參數而不是刪除參數會發生什麼? –
嘿,是的,我可以重現這種行爲;那...看起來像一個CLR bug?我同意這當然不直觀 –
特別好奇的是,它甚至通過了IL檢查 - 「peverify」完全滿意它(儘管這可能不是在IL中完成的,需要推遲到運行時)。實質上,委託構造函數的'native int'參數(表示函數)未驗證匹配,看起來好像是 –