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

  • 相关阅读:
    FZU 2112 并查集、欧拉通路
    HDU 5686 斐波那契数列、Java求大数
    Codeforces 675C Money Transfers 思维题
    HDU 5687 字典树插入查找删除
    HDU 1532 最大流模板题
    HDU 5384 字典树、AC自动机
    山科第三届校赛总结
    HDU 2222 AC自动机模板题
    HDU 3911 线段树区间合并、异或取反操作
    CodeForces 615B Longtail Hedgehog
  • 原文地址:https://www.cnblogs.com/waw/p/2157086.html
Copyright © 2011-2022 走看看