2013-03-07 23 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的情況,則會發現此類模型將準確預測事物會表現出來。

相關問題