对于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 modif
ying 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:08

对于C#中b=a的N种情况分析的相关文章

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

本文旨在验证一个容易混淆的概念,从而为<玩转WPF/Silverlight中INotifyPropertyChanged和ObservableCollection>做铺垫. 两个相同类型的变量a和b,并且有如下关系:        b = a; 如果a发生改变,b是否也发生改变呢? 情况很复杂,分以下几种情况谈论:       1) 单个实体             1. 简单类型             先考察int:             int a = 1;            in

通过JDBC操纵Oracle数据库LOB字段的几种情况分析

oracle|数据|数据库 通过JDBC操纵Oracle数据库LOB字段的几种情况分析纵横软件制作中心 雨亦奇2003-6-10 15:14:19在Oracle中,LOB(Large Object,大型对象)类型的字段现在用得越来越多了.因为这种类型的字段,容量大(最多能容纳4GB的数据),且一个表中可以有多个这种类型的字段,很灵活,适用于数据量非常大的业务领域(如图象.档案等).而LONG.LONG RAW等类型的字段,虽然存储容量也不小(可达2GB),但由于一个表中只能有一个这样类型的字段的

HTML中调用JavaScript的几种情况和规范写法

JavaScript运行在html中,引用有几种方式? 我知道的方法有3种: 第一种:外部引用远程JavaScript文件,如<script type="text/javascript" src="../js/jquery-1.8.3.js"></script>(相对路劲)或者是<script src="http://common.cnblogs.com/script/jquery.js" type="te

SQLServer 数据库备份过程中经常遇到的九种情况_MsSql

第一种情况: 有RAID,还需要做数据库备份吗? 回答:需要.有了RAID,万一部份磁盘损坏,可以修复数据库,有的情况下数据库甚至可以继续使用.但是,如果哪一天,你的同事不小心删除了一条重要的记录,怎么办?RAID是无能为力的.你需要合适的备份策略,把那条被误删的数据恢复出来.所以有了RAID,仍需要做备份集群,磁盘镜像同理. 第二种情况: 我们需要全备份+日志备份? 解答:如果你只做全备份,那么受限于全备份的大小和备份时间,不可能常做.而且只有全备份,不能将数据库恢复至某个时间点.所以,我们需

SQLServer 数据库备份过程中经常遇到的九种情况

第一种情况: 有RAID,还需要做数据库备份吗? 回答:需要.有了RAID,万一部份磁盘损坏,可以修复数据库,有的情况下数据库甚至可以继续使用.但是,如果哪一天,你的同事不小心删除了一条重要的记录,怎么办?RAID是无能为力的.你需要合适的备份策略,把那条被误删的数据恢复出来.所以有了RAID,仍需要做备份集群,磁盘镜像同理. 第二种情况: 我们需要全备份+日志备份? 解答:如果你只做全备份,那么受限于全备份的大小和备份时间,不可能常做.而且只有全备份,不能将数据库恢复至某个时间点.所以,我们需

PHP获取客户端真实IP地址的5种情况分析和实现代码_php实例

在PHP获取客户端IP中常使用 $_SERVER["REMOTE_ADDR"] . (1) 但如果客户端是使用代理服务器来访问,那取到的是代理服务器的 IP 地址,而不是真正的客户端 IP 地址.要想透过代理服务器取得客户端的真实 IP 地址,就要使用 $_SERVER["HTTP_X_FORWARDED_FOR"] 来读取. (2) 但只有客户端使用"透明代理"的情况下,$_SERVER["HTTP_X_FORWARDED_FOR&q

mysql索引失效的五种情况分析_Mysql

索引并不是时时都会生效的,比如以下几种情况,将导致索引失效: 如果条件中有or,即使其中有条件带索引也不会使用(这也是为什么尽量少用or的原因) 注意:要想使用or,又想让索引生效,只能将or条件中的每个列都加上索引 2.对于多列索引,不是使用的第一部分,则不会使用索引 3.like查询是以%开头 4.如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不使用索引 5.如果mysql估计使用全表扫描要比使用索引快,则不使用索引 此外,查看索引的使用情况 show status lik

Mysql索引会失效的几种情况分析_Mysql

索引并不是时时都会生效的,比如以下几种情况,将导致索引失效:     1.如果条件中有or,即使其中有条件带索引也不会使用(这也是为什么尽量少用or的原因) 注意:要想使用or,又想让索引生效,只能将or条件中的每个列都加上索引 2.对于多列索引,不是使用的第一部分,则不会使用索引 3.like查询是以%开头     4.如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不使用索引 5.如果mysql估计使用全表扫描要比使用索引快,则不使用索引 此外,查看索引的使用情况show s

网站收录时出现的几种情况分析

摘要: 最近打开电脑做的第一件事情不是去看数据变化,而是首先打开网站查看百度对于网站的文章是否收录,很奇怪事情发生了.不知道大家有没有遇到这样的事情,网站主页收录都是隔天 最近打开电脑做的第一件事情不是去看数据变化,而是首先打开网站查看百度对于网站的文章是否收录,很奇怪事情发生了.不知道大家有没有遇到这样的事情,网站主页收录都是隔天收录,但是内页不知道为什么就是不收录,我做的6788中国创业网,6788.cn(Ps:这就包括了内页的一些站)收录1万三,主页3www的收录竟然达到了一万1800,这