字符串具有值类型的特点对字符串,对同一个字符串大量修改或者对多个引用赋值同一个字符串对象时会产生大量的临时字符串对象,影响性能,但是CLR为我们做了一些工作来消除这些弊端。

     对同一个字符串大量修改的问题可以使用StringBulid来解决这个问题,看看下面这个例子:

private string item = "string";

  public void TestStringBuild()

  {

   long sbStart = DateTime.Now.Ticks;

   UseStrigBuilder(1000);

   long sbEnd = DateTime.Now.Ticks;

   Console.WriteLine("使用StringBuilder消耗时间: "+(sbEnd-sbStart).ToString());

   long strStart = DateTime.Now.Ticks;

   UseString(1000);

   long strEnd = DateTime.Now.Ticks;

   Console.WriteLine("使用String消耗时间:"+(strEnd-strStart).ToString());

}

  public string UseStrigBuilder(int number)

  {

   StringBuilder sb = new StringBuilder();

   for(int i = 0; i < number; i++)

   {

    sb.Append(item);

    

   }

   sb.Remove(sb.Length-1 , 1);

   return sb.ToString();

  }

  public string UseString(int number)

  {

   string result = "";

   for(int i = 0; i < number; i++)

   {

    result += item;

   }

   return result;

  }

输出结果为
     

注:DateTime.Now.Ticks:此属性的值表示自 0001 年 1 月 1 日午夜 12:00:00 以来已经过的时间的以 100 毫微秒为间隔的间隔数。 

就是说这1000次循环如果使用StringBuilder的话节省了15625000毫秒的时间。

      第二个问题,对多个引用赋值同一个字符串对象,CLR的解决方法更加巧妙。在默认情况下CLR会使用字符串池的机制,CLR启动的时候,在内部创建一个容器,它以键值对的形式存在,键值是字符串对象内容,值是字符串在托管堆上的引用,当一个新的字符串对象创建的时候CLR检查在这些值中是否已经存在这个字符串对象,如果已经存在就返回对应的值,也就是在托管堆中的引用,如果不存在就在这个容器中中开辟空间存放这个字符串,返回在他的引用。

      这里还是用一段代码来说明:

  public void StringPoolTest()

  {

   string str1 = "789";

   string str2 = "789";

   Console.WriteLine(Object.ReferenceEquals(str1 , str2));

   string str3 = "7" + "8" + "9";

   Console.WriteLine(Object.ReferenceEquals(str1, str3));

   char[] chars = new char[] { '7', '8', '9' };

   string str4 = new string(chars);

   Console.WriteLine(object.ReferenceEquals(str1 , str4));

  }

输出结果:


前两次都输出true说明str1和str2都指向同一个堆引用,最后一个输出false是因为它使用new关键字进行内存分配,字符串池机制不起作用。

这里注意string str3 = "7" + "8" + "9";这个语句在正常的情况下只分配了一次内存,这个也是CLR的优化,在这里就没有分配内存了,因为str1这里已经分配好了。

作者:Tyler
Ning
 

出处:http://www.cnblogs.com/tylerdonet/ 

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,如有问题,可以通过以下邮箱地址williamningdong@gmail.com 联系我,非常感谢。

我不知道的C#—字符串池机制的更多相关文章

  1. 不得不知道的Python字符串编码相关的知识

    开发经常会遇到各种字符串编码的问题,例如报错SyntaxError: Non-ASCII character 'ascii' codec can't encode characters in posi ...

  2. 你可能不知道的jvm的类加载机制

    引言:在java代码中,类型的加载.连接与初始化过程都是在程序运行期间完成的. 加载:查找并加载类的二进制数据(class文件加载到内存中) 连接:a 验证:确保被加载类的正确性. b准备:为类的静态 ...

  3. 【转载】不得不知道的Python字符串编码相关的知识

    原文地址:http://www.cnblogs.com/Xjng/p/5093905.html 开发经常会遇到各种字符串编码的问题,例如报错SyntaxError: Non-ASCII charact ...

  4. 你所不知道的Python | 字符串连接的秘密

    字符串连接,就是将2个或以上的字符串合并成一个,看上去连接字符串是一个非常基础的小问题,但是在Python中,我们可以用多种方式实现字符串的连接,稍有不慎就有可能因为选择不当而给程序带来性能损失. 方 ...

  5. 你所不知道的库存超限做法 服务器一般达到多少qps比较好[转] JAVA格物致知基础篇:你所不知道的返回码 深入了解EntityFramework Core 2.1延迟加载(Lazy Loading) EntityFramework 6.x和EntityFramework Core关系映射中导航属性必须是public? 藏在正则表达式里的陷阱 两道面试题,带你解析Java类加载机制

    你所不知道的库存超限做法 在互联网企业中,限购的做法,多种多样,有的别出心裁,有的因循守旧,但是种种做法皆想达到的目的,无外乎几种,商品卖的完,系统抗的住,库存不超限.虽然短短数语,却有着说不完,道不 ...

  6. Java并发编程(您不知道的线程池操作), 最受欢迎的 8 位 Java 大师,Java并发包中的同步队列SynchronousQueue实现原理

    Java_并发编程培训 java并发程序设计教程 JUC Exchanger 一.概述 Exchanger 可以在对中对元素进行配对和交换的线程的同步点.每个线程将条目上的某个方法呈现给 exchan ...

  7. Java并发编程(您不知道的线程池操作)

    Java并发编程(您不知道的线程池操作) 这几篇博客,一直在谈线程,设想一下这个场景,如果并发的线程很多,然而每个线程如果执行的时间很多的话,这样的话,就会大量的降低系统的效率.这时候就可以采用线程池 ...

  8. 1.字符串池化(intern)机制及拓展学习

    1.字符串intern机制 用了这么久的python,时刻和字符串打交道,直到遇到下面的情况: a = "hello" b = "hello" print(a ...

  9. 你所不知道的setTimeout

    JavaScript提供定时执行代码的功能,叫做定时器(timer),主要由setTimeout()和setInterval()这两个函数来完成.它们向任务队列添加定时任务.初始接触它的人都觉得好简单 ...

随机推荐

  1. 计算IMEI号的校验位

    计算IMEI号的校验位 移动设备国际识别码(IMEI:International Mobile Equipment Identification Number)是差别移动设备的标志,具有唯一性,贴在手 ...

  2. 【BZOJ2521】[Shoi2010]最小生成树 最小割

    [BZOJ2521][Shoi2010]最小生成树 Description Secsa最近对最小生成树问题特别感兴趣.他已经知道如果要去求出一个n个点.m条边的无向图的最小生成树有一个Krustal算 ...

  3. java读流方式,下载网络上的图片

    本工具类支持url的list集合,具体实现如下所示: public static void download(ArrayList<String> listUrl, String downl ...

  4. R in Action(1) 基本数据结构

    一数据类型 R的数据类型包括数值型.字符型.逻辑型(布尔).复数型和原生型,同时R有好多存储数据的对象类型,包括标量.向量.矩阵.数组.数据框和列表,如下图所示下图(图的版权神马的归原作者跟原出版社所 ...

  5. Cocos2d-x动画播放(序列帧)

    简介 Cocos2d-x中,动画的具体内容是依靠精灵显示出来的,为了显示动态图片,我们需要不停切换精灵显示的内容,通过把静态的精灵变为动画播放器从而实现动画效果.动画由帧组成,每一帧都是一个纹理,我们 ...

  6. Gym - 100283K K. Cubes Shuffling —— 贪心

    题目链接:http://codeforces.com/gym/100283/problem/K 题解: 要使其相邻两项的差值之和最小,那么越靠中间,其数值越小. 那么剩下的问题就是如何放数字了.一开始 ...

  7. yum的配置文件yum.conf详解

    说明:经过网上抄袭和自己的总结加实验,非常详细,可留作参考. yum的配置一般有两种方式:   一种是直接配置/etc目录下的yum.conf文件, 另外一种是在/etc/yum.repos.d目录下 ...

  8. 理解数学公式与numpy矩阵运算

    1.矩阵的初始化 (1)创建一个 3*5的全0矩阵和全1矩阵 import numpy as np myzero = np.zeros([3,5]) print myzero myones = np. ...

  9. 机器学习(十六)— LDA和PCA降维

    一.LDA算法 基本思想:LDA是一种监督学习的降维技术,也就是说它的数据集的每个样本是有类别输出的.这点和PCA不同.PCA是不考虑样本类别输出的无监督降维技术. 我们要将数据在低维度上进行投影,投 ...

  10. python berkeley DB操作——打开btree索引文件中的database

    打开BDB中某个索引中的数据库代码: from bsddb3 import db import bsddb3 as bsddb print db.DB_VERSION_STRING mydb = db ...