使用值类型和引用类型时,为什么Interfaces行为会有所不同

时间:2013-03-07 18:31:15

标签: c# interface value-type reference-type

我在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);
        }
    }

在Main:

    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);  

但是,如果我将struct的定义更改为类,如:

class SomeValueType : IChangeable

它写7而不是2。

2 个答案:

答案 0 :(得分:2)

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

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

请参阅MSDN上的Value Types and Reference Types

答案 1 :(得分:0)

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

虽然C#以假装存储位置类型和堆对象类型是同一种方式定义术语“继承”,但这两种类型的行为会有所不同。将值类型转换为它表示的接口将生成一个新的堆对象,该对象包含已转换的值类型的公共和私有字段的副本,然后返回对该新实例的引用。结果引用将显示引用语义,因为它将是一个引用。

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