艾伟_转载:对于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);

            输出结果:

           

            再考察一下string:

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

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

            输出结果:

           

            如果不放心,还可以测试一下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);

            输出结果:

           

            结论: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);

            输出结果:

           

            结论:对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);

            输出结果:

           

            结论:问题集中在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);

            输出结果:

           

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

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

      示例代码下载:TestEqual.zip

时间: 2024-08-02 01:18:12

艾伟_转载:对于C#中b=a的N种情况分析的相关文章

对于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(&

艾伟_转载:TreeView节点定位的另外一种方法TreeNode.FromHandle

Winform 里面的TreeView是一种常见的.功能强大的控件,一般的使用大家可能都是比较熟悉的了,估计我们大多数做定位节点的时候,一般都是采用循环查找的方法.如下面的方法所示 foreach (TreeNode node in this.TreeView1.Nodes) {if (node.Text == "要找的节点名称") {return node; }return null; } 另外还有一种方法是使 用TreeNode.FromHandle方法来快速定位节点,为了说明如何

艾伟_转载:在Mono中创建ASP.NET程序

一只可爱的猴子: 一次偶然的机会碰到这只猴子,并在工作中也用到它了.现将自己的使用经验分享与此(以OpenSUSE为例介绍). 对于不熟悉Mono的朋友来说,Mono就是.Net在Linux和其它操作系统上的实现(Unix.Mac.iphone.Windows...).Mono的官方网站是:http://www.mono-project.com 严格来讲,Mono是一个开源的.跨平台的C#语言和其CLR的实现,并与微软的.NET二进制兼容.很绕口吧,这是Mono官方网站写的:An open so

艾伟_转载:.NET Discovery 系列之二--string从入门到精通(勘误版下)

本系列文章导航 .NET Discovery 系列之一--string从入门到精通(上) .NET Discovery 系列之二--string从入门到精通(勘误版下) .NET Discovery 系列之三--深入理解.NET垃圾收集机制(上) .NET Discovery 系列之四--深入理解.NET垃圾收集机制(下) .Net Discovery 系列之五--Me JIT(上) .NET Discovery 系列之六--Me JIT(下) .NET Discovery 系列之七--深入理解

艾伟_转载:正则表达式30分钟入门教程

  本文目标 30分钟内让你明白正则表达式是什么,并对它有一些基本的了解,让你可以在自己的程序或网页里使用它. 如何使用本教程 最重要的是--请给我30分钟,如果你没有使用正则表达式的经验,请不要试图在30秒内入门--除非你是超人 :) 别被下面那些复杂的表达式吓倒,只要跟着我一步一步来,你会发现正则表达式其实并没有你想像中的那么困难.当然,如果你看完了这篇教程之后,发现自己明白了很多,却又几乎什么都记不得,那也是很正常的--我认为,没接触过正则表达式的人在看完这篇教程后,能把提到过的语法记住8

艾伟_转载:把委托说透(2):深入理解委托

在上一篇随笔中我们通过示例逐步引入了委托,并比较了委托和接口.本文将重点剖析委托的实质. 委托在本质上仍然是一个类,我们用delegate关键字声明的所有委托都继承自System.MulticastDelegate.后者又是继承自System.Delegate类,System.Delegate类则继承自System.Object.委托既然是一个类,那么它就可以被定义在任何地方,即可以定义在类的内部,也可以定义在类的外部. 正如很多资料上所说的,委托是一种类型安全的函数回调机制, 它不仅能够调用实

艾伟_转载:揭示同步块索引(上):从lock开始

大家都知道引用类型对象除实例字段的开销外,还有两个字段的开销:类型指针和同步块索引(SyncBlockIndex).同步块索引这个东西比起它的兄弟类型指针更少受人关注,显得有点冷落,其实此兄功力非凡,在CLR里可谓叱咤风云,很多功能都要借助它来实现. 接下来我会用三篇来介绍同步块索引在.NET中的所作所为. 既然本章副标题是从lock开始,那我就举几个lock的示例: 代码1 1: public class Singleton 2: { 3: private static object lock

艾伟_转载:谈*静态页*(或网页*静态化*)

"静态页",在Web应用程序开发中是很常见的概念.只是我发现目前还是有相当部分的朋友,在这方面的存在一定的误区.因此现在独立写一篇文章,也想把一些问题讲讲清楚,以后在讨论的时候也好有个准. 不久前有朋友写了一篇题为<提供生成静态页核心代码>的文章,介绍了一种"向硬盘写入页面文件"的方式.这篇文章的内容在此并不多作讨论,这里引用一下作者给出的摘要: 网页生成静态Html文件有许多好处,比如生成html网页有利于被搜索引擎收录,不仅被收录的快还收录的全.前台

艾伟_转载:使用LINQ to SQL更新数据库(上):问题重重

在学习LINQ时,我几乎被一个困难所击倒,这就是你从标题中看到的更新数据库的操作.下面我就一步步带你走入这泥潭,请准备好砖头和口水,Follow me. 从最简单的情况入手 我们以Northwind数据库为例,当需要修改一个产品的ProductName时,可以在客户端直接写下这样的代码: // List 0NorthwindDataContext db = new NorthwindDataContext(); Product product = db.Products.Single(p =>