开发者社区> 狼人2007> 正文

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

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

  本文旨在验证一个容易混淆的概念,从而为《玩转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

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
如何设置阿里云服务器安全组?阿里云安全组规则详细解说
阿里云安全组设置详细图文教程(收藏起来) 阿里云服务器安全组设置规则分享,阿里云服务器安全组如何放行端口设置教程。阿里云会要求客户设置安全组,如果不设置,阿里云会指定默认的安全组。那么,这个安全组是什么呢?顾名思义,就是为了服务器安全设置的。安全组其实就是一个虚拟的防火墙,可以让用户从端口、IP的维度来筛选对应服务器的访问者,从而形成一个云上的安全域。
19810 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,阿里云优惠总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系.
29185 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,大概有三种登录方式:
13575 0
阿里云服务器安全组设置内网互通的方法
虽然0.0.0.0/0使用非常方便,但是发现很多同学使用它来做内网互通,这是有安全风险的,实例有可能会在经典网络被内网IP访问到。下面介绍一下四种安全的内网互联设置方法。 购买前请先:领取阿里云幸运券,有很多优惠,可到下文中领取。
22540 0
阿里云服务器ECS登录用户名是什么?系统不同默认账号也不同
阿里云服务器Windows系统默认用户名administrator,Linux镜像服务器用户名root
16459 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
20705 0
腾讯云服务器 设置ngxin + fastdfs +tomcat 开机自启动
在tomcat中新建一个可以启动的 .sh 脚本文件 /usr/local/tomcat7/bin/ export JAVA_HOME=/usr/local/java/jdk7 export PATH=$JAVA_HOME/bin/:$PATH export CLASSPATH=.
14900 0
+关注
狼人2007
个人对技术的追求:代码少而精捍;思路清晰美观;可扩展好维护;技术驱动商业; 人生格言:只要你有信念,有追求,并且坚持,那你一定比随波逐流,行得远行得正...
3523
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
JS零基础入门教程(上册)
立即下载
性能优化方法论
立即下载
手把手学习日志服务SLS,云启实验室实战指南
立即下载