跨未装箱变量传播更改

本文关键字:传播 变量 | 更新日期: 2023-09-27 18:07:07

我只是做了一个小实验,看看改变一个未装箱的变量是否会传播对原始源代码所做的更改,并根据我使用的类型得到了两个完全不同的结果。我主要感兴趣的是为WPF数据绑定应用程序弄清楚这一点,在这些应用程序中,我绑定到object、转换、更改,并希望原始的更新它们的ui。

结果如下:

  1. 简单类型在拆箱后似乎失去了对原始源的引用。
  2. 自定义类型似乎保留了它们的引用。

似乎我没有什么可担心的,在我的情况下,希望我的WPF UI更新自己后对未装箱绑定的数据上下文进行更改;然而,不知道为什么这种情况只发生在复杂的对象上,这让我有点担心。我不希望我的UI在我不知道的罕见或奇怪的情况下失败。有人能解释一下后面发生的机械现象吗?

class Program
{
    //simple types
    private static object sbox1;
    private static object sbox2;
    private static int svalue1 = 10;
    private static int svalue2 = 15;
    //custom types
    private static MyType cvalue1;
    private static MyType cvalue2;
    private static object cbox1;
    private static object cbox2;
    static void Main(string[] args)
    {
        //Box up the values
        sbox1 = svalue1;
        sbox2 = svalue2;
        //unbox the values to local var
        var sunboxed1 = (int)sbox1;
        var sunboxed2 = (int)sbox2;
        //change the values in the new unboxed vars
        sunboxed1 = -10;
        sunboxed2 = -15;
        //check unboxed values and check original value variables
        Console.WriteLine("unboxed1 = " + sunboxed1);
        Console.WriteLine("unboxed2 = " + sunboxed2);
        Console.WriteLine("value1 = " + svalue1);
        Console.WriteLine("value2 = " + svalue2);
        //Now try hand at custom types
        cvalue1 = new MyType() { Example = "I am cvalue1's original string." };
        cvalue2 = new MyType() { Example = "I am cvalue2's original string." };
        //now box them up.
        cbox1 = cvalue1;
        cbox2 = cvalue2;
        //now unbox and change the strings
        var cunboxed1 = cbox1 as MyType;
        var cunboxed2 = cbox2 as MyType;
        //change the original strings to see if they propogate to original objects
        cunboxed1.Example = "I am cunboxed1's altered string.";
        cunboxed2.Example = "I am cunboxed2's altered string.";
        //print unboxed and originals values to compare
        Console.WriteLine("cunboxed1.Example = " + cunboxed1.Example);
        Console.WriteLine("cunboxed2.Example = " + cunboxed2.Example);
        Console.WriteLine("cvalue1.Example = " + cvalue1.Example);
        Console.WriteLine("cvalue2.Example = " + cvalue2.Example);
        Console.ReadKey();
    }
}
class MyType
{
    public string Example { get; set; }
}

测试程序的结果:

unboxed1 = -10  
unboxed2 = -15  
value1 = 10  
value2 = 15  
cunboxed1.Example = I am cunboxed1's altered string.  
cunboxed2.Example = I am cunboxed2's altered string.  
cvalue1.Example = I am cunboxed1's altered string.  
cvalue2.Example = I am cunboxed2's altered string.  

跨未装箱变量传播更改

您所看到的是由值和引用类型的不同处理引起的。在第一个示例中,您正在拳击一个int。它被包装在Int32(一个值类型)中,并分配给object变量。在开箱步骤中,复制原始的Int32对象,因为它是一个值类型,并且将其值分配给int变量sunboxed1sbox1sunboxed1保存不同的值,并且存在于不同的内存位置,因此对其中一个的更改不会影响另一个。

在第二个示例中,您将一个类分配给object变量。这不是给它装箱;您只是将对象的引用向上转换。当您随后使用as关键字将其向下转换回MyType时,您将获得对原始对象的引用。因此,cvalue1cunboxed1持有对同一对象的引用。

正如dotnettom所说,这更多的是关于值类型和引用类型。

根据MSDN http://msdn.microsoft.com/en-us/library/t63sy5hs.aspx
如果数据类型将数据保存在自己的内存分配中,则该数据类型是值类型。取值类型包括:所有数字数据类型....

但是,对于类:
引用类型包含指向保存该数据的另一个内存位置的指针。类类型,例如Form.....

最后一行是最有趣的。
类是引用类型。因此,. net框架类支持诸如Object和String之类的引用类型。注意,每个数组都是引用类型,即使它的成员是值类型

这就是为什么上面的自定义类型在拆箱后改变了上面的原始值。字符串本身是引用类型,所以看起来变化的原因是由于我使用字符串作为示例而不是数字类型;但是,将Example属性更改为int仍然会更改原始源代码并产生相同的结果。