本文介绍C#中的string是一个引用类型,C# String对象是存放在堆上,而不是堆栈上的,因此,当把一个字符串变量赋给另一个字符串时,会得到对内存中同一个字符串的两个引用。

AD:WOT2015 互联网运维与开发者大会 热销抢票

大家都知道,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对象的,编译器会报错。

浅谈C# String对象的更多相关文章

  1. C#核心基础--浅谈类和对象的概念

    浅谈类和对象的概念 一.什么是类?什么是对象? 学习一门面向对象编程语言,我们必须得知道什么是类?什么是对象? 类(Class)实际上是对某种类型的对象定义变量和方法的原型.它表示对现实生活中一类具有 ...

  2. 浅谈Java回收对象的标记和对象的二次标记过程_java - JAVA

    文章来源:嗨学网 敏而好学论坛www.piaodoo.com 欢迎大家相互学习 一.对象的标记 1.什么是标记?怎么标记? 第一个问题相信大家都知道,标记就是对一些已死的对象打上记号,方便垃圾收集器的 ...

  3. 浅谈JavaScript原型对象与相关设计模式

    引言 本文先从介绍JavaScript中基本的几种设计模式开始,最后引出原型对象,然后对原型对象有一个较全面的介绍. 1.创建对象的几种设计模式 A.工厂模式 我们知道在JavaScript中创建对象 ...

  4. 浅谈python的对象的三大特性之封装

    我们家里都有电视机,从开机,浏览节目,换台到关机,我们不需要知道电视机里面的具体细节,只需要在用的时候按下遥控器就可以完成操作,这就是功能的封装. 在用支付宝进行付款的时候,只需要在用的时候把二唯码给 ...

  5. 浅谈python的对象的三大特性之继承

    前面我们定义了人的类,并用这个类实例化出两个人jack和lily,查看了它们的内存空间. 现在我们再来看看类中所存在的对向对象编程的三大特性之继承的一些特性. 前面定义了一个人的类,可是我们还知道,人 ...

  6. 浅谈C++中对象的复制与对象之间的相互赋值

    C++对象的复制 有时需要用到多个完全相同的对象,例如,同一型号的每一个产品从外表到内部属性都是一样的,如果要对每一个产品分别进行处理,就需要建立多个同样的对象,并要进行相同的初始化,用以前的办法定义 ...

  7. 浅谈 Objective-C 下对象的初始化

    转自:http://www.oschina.net/question/54100_32468 众所周知,Objective-C是一门面向对象的语言,一般情况下,我们在Objective-C中定义一个类 ...

  8. jsp内置对象浅谈

    jsp内置对象浅谈 | 浏览:1184 | 更新:2013-12-11 16:01 JSP内置对象:我们在使用JSP进行页面编程时可以直接使用而不需自己创建的一些Web容器已为用户创建好的JSP内置对 ...

  9. .net中对象序列化技术浅谈

    .net中对象序列化技术浅谈 2009-03-11 阅读2756评论2 序列化是将对象状态转换为可保持或传输的格式的过程.与序列化相对的是反序列化,它将流转换为对象.这两个过程结合起来,可以轻松地存储 ...

随机推荐

  1. HDU 4622 Reincarnation 后缀自动机 // BKDRHash(最优hash)

    Reincarnation Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others) P ...

  2. zoj 2271 Chance to Encounter a Girl <概率DP>

    题目: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2271 题意:一个N*N的矩阵( N = 2*k-1 , k< ...

  3. 深入浅出谈DM

  4. 对私有API提交的注意事项

    1.这个等于堵死了调试断点.关闭就不能断点调试了. 2.对于敏感的函数名要做一个对称加密处理. 防止二进制文件的静态扫描. 3.对于调用私有函数的方法,可以做一个宏定义包装. #define 你的正常 ...

  5. Double.valueOf()与Double.parseDouble()两者的区别

    写代码用到这两个方法,不知道有什么区别,看一下源码: Double.parseDouble(String str) public static double parseDouble(String s) ...

  6. 棋盘覆盖问题 (粉书 P230 【递归】** )

    转载自:http://blog.csdn.net/akof1314/article/details/5423608  (赞) 在一个 2^k * 2^k 个方格组成的棋盘中,若恰有一个方格与其它方格不 ...

  7. HashMap vs ConcurrentHashMap — 示例及Iterator探秘

    如果你是一名Java开发人员,我能够确定你肯定知道ConcurrentModificationException,它是在使用迭代器遍历集合对象时修改集合对象造成的(并发修改)异常.实际上,Java的集 ...

  8. 关于“C++语言程序设计”书的一个类

    class book{    char* title;    int num_pages;    int cur_page;public:    book(const char* theTitle, ...

  9. ubuntu 16.04 apt-get 出现The package 'xxx' needs to be reinstalled, but I can't find an archive for it.

    参考网址:http://www.ihaveapc.com/2011/10/fix-annoying-the-package-needs-to-be-reinstalled-but-i-cant-fin ...

  10. Microsoft visual studio关闭安全检查

    在用Microsoft visual studio进行代码编写时,使用到列如sprintlf这种比较旧的指令,需要关闭Microsoft visual studio的安全检查: 设置预处理选项:a. ...