2015-02-08 97 views
4

對於這個代碼:IL約束呼叫

class Program 
{ 
    static void Main() 
    { 
     Console.WriteLine(new MyStruct().ToString()); 
    } 

    struct MyStruct { } 
} 

C#編譯器生成constrained callvirt IL代碼。

This文章說:

例如,如果一個值V型覆蓋Object.ToString()方法,呼叫V.ToString()指令發出;如果沒有,則會發出一個盒子指令和一個callvirt Object.ToString()指令。版本問題可能會出現< ...>如果稍後添加覆蓋。

所以,我的問題是:如果編譯器會生成box代碼,而不是受限制的調用,爲什麼會出現這種情況?

+0

沒有你已經提供的鏈接解釋它,只是你的報價才道:「使用受限的前綴也避免了值類型的潛在版本問題如果不使用受限制的前綴,不同的IL必須根據發射。關於值類型是否覆蓋System.Object的一個方法。「 – 2015-02-08 15:08:27

+0

@Selman22,這就是我問的原因。我不明白爲什麼它不能僅僅是盒裝callvirt。 – aush 2015-02-08 15:12:32

回答

7

box指令創建相關實例的副本。允許值類型的實例方法修改它們被調用的實例,如果它們這樣做,在副本上靜靜地調用方法是錯誤的。

static class Program 
{ 
    static void Main() 
    { 
     var myStruct = new MyStruct(); 
     Console.WriteLine(myStruct.i); // prints 0 
     Console.WriteLine(myStruct.ToString()); // modifies myStruct, not a copy of myStruct 
     Console.WriteLine(myStruct.i); // prints 1 
    } 

    struct MyStruct { 
     public int i; 
     public override string ToString() { 
      i = 1; 
      return base.ToString(); 
     } 
    } 
}