2015-02-08 119 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(); 
     } 
    } 
}