好久没写文章了,再拿起这本书,学习加分享,乐趣无穷啊。这两天看了写关于字符串的知识,从学写代码的时候开始,我们就基本天天跟String打交道,对它再熟悉不过了。但是仔细看看,还是有一种拨开云雾的感觉,对平日里的一些问题顿然明白了。


一、 string实例化

1. 创建string对象

string str1 = "hello world."; //√

string str2 = new string("hello world"); //×

按照错误提示试一下char[]类型参数发现可以的:

string str2 = new string(new char[] { 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd' });//√

2.IL代码

string str1=”hello world”; 对应的IL代码为:

我们知道实例化引用类型时对应的IL代码为newobj,但是通过上图我们发现string类型比较特殊,使用的ldstr(load string)指令来构建对象。

3. 几点说明:

  • String 直接继承自System.Object,它是引用类型,其实例存储在堆上。而且string是密封类,它是不能够被继承的。
  • 换行:提倡使用Envionment.NewLine进行换行而不是转义字符,因为NewLine会根据平台返回相应的字符,及时跨平台也能正常运行。
  • @符号:文件路径或者正则表达式中出现斜线时,为了防止误当做转义字符,可以在字符串前添加@。例如@"D:\CLRviaC#\Demo01"。
  • string和System.String:System.String是.net framework中定义的一个类型,string是C#定义的一个关键字,代表System.String这种类型,可认为是System.String的简写形式。之前一直认为它是基元类型,经IsPrimitive方法验证其实并不是。(多谢Fish Li指正)。
  • ToString()方法:基类System.Object中包含了该方法,一般在具体使用时会重新定义该类。这个方法比较熟悉,就不赘述了。

二、 字符串驻留

1. 字符串的特色之一就是恒定不变,对于字符串的任何操作(如SubString,ToUpper等)其实都是生成了一个新的字符串,原字符串是保留不变的。

我们来看个例子来验证一下是不是这样的:

//①
string str1 = "HelloWorld";
string str2 = "HelloWorld";
Console.WriteLine(ReferenceEquals(str1, str2));
//②
string str3 = "Hello" + "World";
Console.WriteLine(ReferenceEquals(str1, str3));
//③
string str4 = "Hello";
string str5 = "World";
string str6 = str4 + str5;
Console.WriteLine(ReferenceEquals(str1, str6));
//④
str6 = string.Intern(str6);
Console.WriteLine(ReferenceEquals(str1, str6));

运行结果跟之前的预测或许会有些出入,这是因为CLR使用了字符串驻留的技术,它是通过创建一个哈希表来实现的,其中Key是字符串,value是对于托管堆中string对象的引用,每当创建新的字符串实例的时候会先检测哈希表中是否已经存在相同的字符串。

具体到上面例子中:

  • ①根据字符串驻留技术,str1和str2字符串内容完全相同,实际上指向了同一个引用;
  • ②用+连接的字符串文本常量str3,在编译期间就已经完成连接动作,所以str3也和str1指向了同一引用;
  • ③str6是在运行时才将str4和str5连接在一起的,这个过程中创建了多个字符串对象,最终str6和str1指向的不是同一个引用。
  • ④调用了String.Intern(string str)方法(下文介绍),强制使用字符串驻留技术,所以str6和str1指向了同一引用。

2. String类两个访问哈希表的方法:

  • Public static string Intern(string str);

获取string类型对象的哈希码,并在哈希表中检查是否有匹配项,如果存在则返回string对象的引用,如果不存在,则将其副本添加到哈希表中然后返回引用。

  • Public static string IsInterned(string str);

与上面的方法类似,不同的是没有匹配项时会返回Null,而不会自动将字符串添加到哈希表中。

3. 驻留虽有用,使用需谨慎

当有大量的字符串操作时,驻留机制确实能够节省内存,但是我们却不能滥用这个机制。写程序的时候不能一直默认该机制的存在,除非我们显式调用String.Intern方法,避免产生意想不到的错误,因为这个机制其实是可以被编译器禁用的,随着.NET版本的变化,不能保证一直默认启用字符串驻留。而且,字符串驻留机制对性能和内存的提高也不是绝对的,因为字符串驻留的过程本身也是需要时间的。总之,使用的时候还是要谨慎一些。

三、 StringBuilder

String类型字符串是恒定不变的,当进行字符串累加等大量的字符串操作时,会占用大量的内存。此时最好使用System.Text.StringBuilder类型。

1. 构造StringBuilder对象

StringBuilder使用new关键字构造对象,不像String类型那样特殊。它有大概6种构造器,主要是用来分配和初始化StringBuilder对象的状态,主要包括:

  • 字符串最大容量,默认是Int32.MaxValue;
  • 字符数组:char结构构成的数组,负责维护字符串中的字符内容;
  • 容量:指定StringBuilder维护的字符数组的长度,默认为16.当容量不足时,会自动倍增。

2.与String类型配合  

StringBuilder可以通过ToString()方法在堆上创建相应的String对象,其中包含了该时刻在StringBuilder中的字符串内容。还可以通过Append()方法等将字符串再次添加到StringBuilder中。

StringBuilder提供的方法与String不是完全对应的,可以巧妙的利用它们配合完成一些字符串操作。其中ToLower,Trim,EndsWith等方法是String具有的,而Replace等方法又是StringBuilder特有的。

例如:

StringBuilder s = new StringBuilder();
s.AppendFormat("{0} {1}", "Cathy", "Chen").Replace(" ","-");
string s1 = s.ToString().ToUpper();
Console.WriteLine(s1);

CLR via C#(15)--String,熟悉而又陌生的更多相关文章

  1. 2017.11.15 String、StringBuffer、StringBuilder的比较(todo)

    参考来自:http://blog.csdn.net/jeffleo/article/details/52194433 1.速度 一般来说,三者的速度是:StringBuilder > Strin ...

  2. [CLR via C#]15. 枚举类型和位标志

    一.枚举类型 枚举类型(enumerated types)定义了一组"符号名称/值"配对. 例如,以下Color类型定义了一组符号,每个符号都标识一种颜色: internal en ...

  3. 【CLR】奇妙的String

    - 一.背景 1. 以下代码的HashCode是否相同,它们是否是同个对象: var A = "ab" + "c"; var B = "abc&quo ...

  4. 【Java面试题】15 String s="Hello"; s=s+“world!”;这两行代码执行后,原始的String对象中的内容到底变了没有?String与StringBuffer的超详细讲解!!!!!

    1.Java中哪些类是不能被继承的? 不能被继承的是那些用final关键字修饰的类.一般比较基本的类型或防止扩展类无意间破坏原来方法的实现的类型都应该是final的,在java中,System,Str ...

  5. Android探索之ContentProvider熟悉而又陌生的组件

    前言: 总结这篇文章之前我们先来回顾一下Android Sqlite数据库,参考文章:http://www.cnblogs.com/whoislcj/p/5506294.html,Android程序内 ...

  6. LINQ to SQL语句(15)之String

    LINQ to SQL支持以下String方法.但是不同的是默认情况下System.String方法区分大小写.而SQL则不区分大小写. 1.字符串串联(String Concatenation) v ...

  7. String的内存模型,为什么String被设计成不可变的

    String是Java中最常用的类,是不可变的(Immutable), 那么String是如何实现Immutable呢,String为什么要设计成不可变呢? 前言 关于String,收集一波基础,来源 ...

  8. 字符、字符串和文本的处理之String类型

    .Net Framework中处理字符和字符串的主要有以下这么几个类: (1).System.Char类 一基础字符串处理类 (2).System.String类 一处理不可变的字符串(一经创建,字符 ...

  9. LINQ体验(11)——LINQ to SQL语句之Null语义和String/DateTime方法

    在本系列中.主要介绍LINQ to SQL基础的东西,由于LINQ太强大了,它对我们寻常使用不同的数据源有着不同的内容,其包含对于SQL Server 数据库的LINQ to SQL:对于XML 文档 ...

随机推荐

  1. iOS 按钮点击变色

    之前一直以为是要在selected状态下增加一个背景图片,效果是颜色变深,明明我的图片是变浅: 之后试了用hightlighted 成功. [_loginBtn setBackgroundImage: ...

  2. VMware克隆SUSE网卡配置

    1.配置DNS vim /etc/resolv.conf domain sitenameserver 202.98.0.682.配置网关 vim /etc/sysconfig/network/rout ...

  3. WCF学习资料汇总

    微软官方讲解教程: 跟我一起从零开始学WCF系列课程 http://msdnwebcast.net/webcast/1/2692/ 构建WCF面向服务的应用程序系列课程 http://msdnwebc ...

  4. linux下查找某个文件位置的方法

    一.通过文件名查找法: 举例说明,假设你忘记了httpd.conf这个文件在系统的哪个目录 下,甚至在系统的某个地方也不知道,则这是可以使用如下命令: find / -name httpd.conf ...

  5. sqlserver 加内置dll的使用内存

  6. Hadoop学习笔记(6) ——重新认识Hadoop

    Hadoop学习笔记(6) ——重新认识Hadoop 之前,我们把hadoop从下载包部署到编写了helloworld,看到了结果.现是得开始稍微更深入地了解hadoop了. Hadoop包含了两大功 ...

  7. iOS 跳转至 指定 StoryBoard 中 指定的 Scene

    UIStoryboard *stryBoard=[UIStoryboard storyboardWithName:@"second" bundle:nil]; UIViewCont ...

  8. Android ScrollView 嵌套 ListView、 ListView 嵌套ScrollView Scroll事件冲突解决办法

    本人菜鸟一名,最近工作了,开始学习Android. 最近在做项目的时候,UX给了个design,大概就是下拉刷新的ListView中嵌套了ScrollView,而且还要在ScrollView中添加动画 ...

  9. 获取table行列

    var table =document.getElementById("add_purchaseOrderDetailList_table"); var rows = table. ...

  10. 基于tensorflow搭建一个神经网络

    一,tensorflow的简介 Tensorflow是一个采用数据流图,用于数值计算的 开源软件库.节点在图中表示数字操作,图中的线 则表示在节点间相互联系的多维数据数组,即张量 它灵活的架构让你可以 ...