2013-03-07 22 views
0

我没有在C#为什么使用值类型和引用类型时,接口的行为不同

interface IChangeable 
    { 
     void Change(params Int32[] array); 
    } 

    struct SomeValueType : IChangeable 
    { 
     private Int32 m_X; 

     public SomeValueType(int X) 
     { 
      m_X = X; 
     } 

     public void Change(params Int32[] array) 
     { 
      m_X = array[0]; 
     } 

     public override string ToString() 
     { 
      return String.Format("Crt value of m_X: {0}", m_X); 
     } 
    } 

而且在主下面的例子:

static void Main(String[] args) 
    { 
     SomeValueType someValueType = new SomeValueType(5); 
     Console.WriteLine(someValueType);         // No boxing occured. It showed: 5 

     Object someRefType = someValueType;         // Boxed 
     Console.WriteLine(someRefType);          // Also Shows 5 (from heap) 

     someValueType.Change(2);           // Change Value of x not o's 
     Console.WriteLine(someValueType + " " + someRefType);    // 2 5 

     ((SomeValueType)someRefType).Change(3);        // Copies to a temp stack so no change ocuured in o 
     Console.WriteLine(someRefType);          // 5 

     IChangeable itfStackChange = (IChangeable)someValueType; 
     itfStackChange.Change(7); 
     Console.WriteLine(someValueType);         // Shows 2 and not 7 ... why? 

     IChangeable itfChange = (IChangeable)someRefType; 
     itfChange.Change(1);            // Unboxes the value of o, making the value of x 1 boxes o again? 
     Console.WriteLine(someRefType);          // Shows 1 
    } 

现在我想知道当我这样做会发生什么:

 IChangeable itfStackChange = (IChangeable)someValueType;  //value was 2 and its still 2 
     itfStackChange.Change(7); 
     Console.WriteLine(someValueType); 

但是,如果我改变结构的定义,类像:

class SomeValueType : IChangeable 

它写出7和不2.

回答

2

值类型语义是使得值沾到分配复制。这意味着当您在赋值后更改时,变量指向不同的对象。

对于参考类型参考被复制,这意味着当您在赋值后更改时,两个变量都指向相同的对象。

Value Types and Reference Types MSDN上。

+0

所以,当我写IChangeable itfStackChange =(IChangeable)someValueType; itfStackChange指向一个复制的someValueType值,我正在修改该复制的值? – Thanatos 2013-03-07 18:36:22

+0

@Thanatos - 是的。 – Oded 2013-03-07 18:49:55

+0

需要注意的是,如果一个存储值类型,接口类型的变量,系统将创建一个新的堆对象实例并存储到一个参考是非常重要的;那个新的实例会像引用类型一样在很多方面表现出来,并且会展现出引用类型的语义。 – supercat 2013-03-07 22:38:18

0

甲结构型定义实际上定义了两种类型的东西:一种存储位置,和一种堆对象的从抽象类继承System.ValueType。堆对象有效地具有相应的存储位置类型的一个字段,但将该存储位置类型的所有成员公开为它自己的字段。对于外部世界来说,堆类型将表现得像一个类对象;然而,在内部,对this的引用是对其对应的存储位置类型的字段的引用。

虽然C#定义以这样的方式来假装存储位置类型和堆对象类型是一个且相同的术语“继承”,两种类型将表现不同。铸造一个值类型,这表示将产生认为被投的值类型的公共和私人领域的复制一个新的堆对象,然后返回一个引用新实例的接口。所得到的参考将展现引用语义,因为它将成为参考。

如果将堆对象和值类型存储位置视为存在于不同的Universe中,并且认识到必须将值从一个Universe复制到另一个Universe的情况,则会发现此类模型将准确预测事物会表现出来。

相关问题