zoukankan      html  css  js  c++  java
  • 艾伟_转载:对于C#中b=a的N种情况分析 狼人:

      本文旨在验证一个容易混淆的概念,从而为《玩转WPF/Silverlight中INotifyPropertyChanged和ObservableCollection》做铺垫。

      两个相同类型的变量a和b,并且有如下关系: 

          b = a;

      如果a发生改变,b是否也发生改变呢?

       情况很复杂,分以下几种情况谈论:

          1) 单个实体

                1. 简单类型

                先考察int:

                int a = 1;
                
    int b = a;

                a 
    = 2;
                Console.WriteLine(
    "b: " + b);

                输出结果:

                clip_image002

                再考察一下string:

                string a = "1";
                
    string b = a;

                a 
    = "2";
                Console.WriteLine(
    "b: " + b);

                输出结果:

                clip_image002[1]

                如果不放心,还可以测试一下Enum,结果类似,详见Demo。

                结论:简单类型是组成复合类型的最基本单位,是原子,不可再拆分,所以不管是值类型double、int还是引用类型string,b都不随a的改变而改变,因为它们指向全局堆栈(对于string而言是托管堆)上的同一个地址。

                2. 复合类型

                复合类型是由string、int、double这些简单类型组成的。

                分别定义一个复合的引用类型(class)和一个复合的值类型(struct)。 

            class UserInfo
            {
                
    public string UserName;
                
    public int Age;
            }

            
    struct UserInfo2
            {
                
    public string UserName;
                
    public int Age;
            }


                先讨论引用类型: 

                UserInfo a = new UserInfo() { UserName = "Baobao", Age = 27 };
                UserInfo b 
    = a;

                a.UserName 
    = "AndersLiu";
                a.Age 
    = 30;

                Console.WriteLine(
    "b.UserName: " + b.UserName);
                Console.WriteLine(
    "b.Age: " + b.Age);

                输出结果:

                clip_image004

                结论:b和a仍然指向托管堆上的同一个UserInfo实例的地址。而UserInfo实例的成员又包含着UserName和Age分别在托管堆和全局堆栈上的地址。所以修改a的成员UserName和Age,只是改变这两个成员的地址,而没有改变UserInfo实例的地址,所以b的成员UserName和Age也会跟着改变。

                让我们局部修改上面的代码:

                UserInfo a = new UserInfo() { UserName = "Baobao", Age = 27 };

                UserInfo b 
    = a;

                
    //a.UserName = "AndersLiu";
                
    //a.Age = 30;

                a 
    = new UserInfo() { UserName = "AndersLiu", Age = 30 };

                Console.WriteLine(
    "b.UserName: " + b.UserName);
                Console.WriteLine(
    "b.Age: " + b.Age);

                输出结果:

                clip_image006

                结论:对a重新进行实例化,导致a指向一个新的UserInfo实例的地址。而b仍然指向原先那个UserInfo实例的地址,所以b不会随着a的改变而改变。从此b和a是两个没有任何关系的变量。

                再来看一下值类型: 

                UserInfo2 a = new UserInfo2() { UserName = "Baobao", Age = 27 };

                UserInfo2 b 
    = a;

                a.UserName 
    = "AndersLiu";
                a.Age 
    = 30;

                Console.WriteLine(
    "b.UserName: " + b.UserName);
                Console.WriteLine(
    "b.Age: " + b.Age);

                输出结果:

                clip_image008

                结论:问题集中在b=a这句话上。这时b指向的是a的一份copy,指向全局堆栈上的与a不同的地址。所以b和a是没有任何关系的,b不随a的改变而改变。


          2) 集合

                1.集合中一笔数据的增删修改。

                List<UserInfo> a = new List<UserInfo>();

                List
    <UserInfo> b = a;

                a.Add(
    new UserInfo() { UserName = "Baobao", Age = 27 });

                Console.WriteLine(
    "b.Count after adding: " + b.Count);
                Console.WriteLine();
                Console.WriteLine(
    "After modifying a[0]");

                a[
    0].UserName = "AndersLiu";
                a[
    0].Age = 30;

                Console.WriteLine(
    "b[0].UserName: " + b[0].UserName);
                Console.WriteLine(
    "b[0].Age: " + b[0].Age);
                Console.WriteLine();

                a.Remove(a[
    0]);

                Console.WriteLine(
    "b.Count after deleting: " + b.Count);

                输出结果:

                clip_image010

                结论:b随着a中数据增减修改而变化。因为b和a指向托管堆上同一个List实例的内存地址,这和复合类型是一样的。

          数组就不说了,可以看作是多个变量的集合,所以按照集合来处理。写了几段测试代码,放在Demo中。

          示例代码下载:TestEqual.zip

  • 相关阅读:
    【CSS】4种CSS方法设置元素垂直水平居中
    js数据类型:引用和5种基本数据类型
    iOS——CALayer的shadow无效问题
    iOS——自定义Segue实现总结
    iOS动画
    iOS——Command-Line 查看当前SDK版本并修改默认SDK版本
    iOS——Swift开发中的单例设计模式(摘译,非原创)
    Windows Phone 8 解锁提示IpOverUsbSvc问题——IpOverUsbEnum返回No connected partners found解决方案
    Windows 8.1 开发过程中遇到的小问题(2)
    Windows 8.1 开发过程中遇到的小问题
  • 原文地址:https://www.cnblogs.com/waw/p/2157086.html
Copyright © 2011-2022 走看看