浅谈C 浅谈重生
创始人
2024-04-28 12:40:53
0次

大家都知道,C#中的string是一个引用类型,C# String对象是存放在堆上,而不是堆栈上的,因此,当把一个字符串变量赋给另一个字符串时,会得到对内存中同一个字符串的两个引用。但是大家有没有想过,为什么修改其中一个字符串,另外一个不受影响呢?

原来,当我们把一个字符串变量赋给另一个字符串时,就会创建一个全新的C# String对象,就是说这个时候就会有两个对象,比如:

  1. classStringExc  
  2. {  
  3. publicstaticvoidMain()  
  4. {  
  5. strings1="originalstring";  
  6. strings2=s1;//注意此时会创建一个新对象  
  7. Console.WriteLine("s1is"+s1);  
  8. Console.WriteLine("s2is"+s2);  
  9. s1="changedstring";  
  10. Console.WriteLine("s1isnow"+s1);  
  11. Console.WriteLine("s2isnow"+s2);  
  12. }  
  13. } 

输出结果为:

  1. s1isoriginalstring  
  2. s2isoriginalstring  
  3. s1isnowchangedstring  
  4. s2isnoworiginalstring 

也就是说,改变s1的值并没有对s2造成任何影响,这与我们平时所说的引用类型的行为正好相反。当用值"original string"初始化s1时,就在堆上分配了一个C# String对象。在初始化s2时,引用也指向这个对象,所以s2的值也是"original string"。但是现在要改变s1的值,而不是替换原来的值时,堆上就会为新值分配一个新对象。s2变量仍然指向原来的对象,所以它的值没有改变。

另外,如果我们像下面这样:

  1. stringstr1="abc";  
  2. stringstr2="abc"; 

当我们用System.Object.Equals(str1,str2)比较时,返回值是true;按理说str1和str2应该指向不同的空间,应该返回false才对啊。原来Equals有三个版本:

  1. publicoverrideboolEquals(object);  
  2. publicboolEquals(string);  
  3. publicstaticboolEquals(string,string); 

前两个实例方法内部会调用CompareOrdinal静态方法,它会字符串中的各个字符,如果相等就返回true。第三个首先会检查两个引用指向的是否是同一个对象,如果是,就返回true,不再去比较各个字符了。

其实CLR使用了一种叫字符串驻留的技术,对于

  1. string   str1="abc";  
  2. string   str2="abc"; 

当CLR初始化时,会创建一个内部的散列表,其中的键为字符串,值为指向托管堆中字符串的引用。刚开始,散列表为空,JIT编译器编译方法时,会在散列表中查找每一个文本常量字符串,首先会查找"abc"字符串,并且因为没有找到,编译器会在托管堆中构造一个新的指向"abc"的C# String对象引用,然后将"abc"字符串和指向该对象的引用添加到散列表中。

接着,在散列表中查找第二个"abc",这一次由于找到了该字符串,所以编译器不会执行任何操作,代码中再没有其它的文本常量字符串,编译器的任务完成,代码开始执行。执行时,CLR发现***个语句需要一个"abc"字符串引用,于是,CLR会在内部的散列表中查找"abc",并且会找到,这样指向先前创建的C# String对象的引用就被保存在变量s1中,执行第二条语句时,CLR会再一次在散列表中查找"abc",并且仍然会找到,指向同一个C# String对象的引用会被保存在变量s2中,到此s1和s2指向了同一个引用,所以System.Object.Equals(s1,s2)就会返回true了。

另外,C#中是不允许用new操作符创建C# String对象的,编译器会报错。

【编辑推荐】

  1. C# Iterator迭代器模式
  2. 概述C# New运算符
  3. C# WiteOne学习笔记
  4. 用C# ListView显示数据记录
  5. C# ConfigDlg.cs源程序

相关内容

热门资讯

PHP新手之PHP入门 PHP是一种易于学习和使用的服务器端脚本语言。只需要很少的编程知识你就能使用PHP建立一个真正交互的...
网络中立的未来 网络中立性是什... 《牛津词典》中对“网络中立”的解释是“电信运营商应秉持的一种原则,即不考虑来源地提供所有内容和应用的...
各种千兆交换机的数据接口类型详... 千兆交换机有很多值得学习的地方,这里我们主要介绍各种千兆交换机的数据接口类型,作为局域网的主要连接设...
粉嫩如何诠释霸道 东芝M805... “霸道粉”是个什么玩意东芝M805拿过来的时候,笔者扑哧笑了,不是笑这款笔记本,而是笑这款产品的颜色...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
什么是大数据安全 什么是大数据... 在《为什么需要大数据安全分析》一文中,我们已经阐述了一个重要观点,即:安全要素信息呈现出大数据的特征...
全面诠释网络负载均衡 负载均衡的出现大大缓解了服务器的压力,更是有效的利用了资源,提高了效率。那么我们现在来说一下网络负载...
如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
只需三步,让你掌握阿尔法路由器... 请参照以下阿尔法路由器设置方法,通过浏览器进入及设置宽带路由器。经过这三个步骤的设置,基本上能够熟悉...
30分钟搞定iOS自定义相机 最近公司的项目中用到了相机,由于不用系统的相机,UI给的相机切图,必须自定义才可以。就花时间简单研究...