跟小静读CLR via C#(15)--String,熟悉而又陌生
好久没写文章了,再拿起这本书,学习加分享,乐趣无穷啊。这两天看了写关于字符串的知识,从学写代码的时候开始,我们就基本天天跟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#(00)-开篇及目录
转载于:https://www.cnblogs.com/janes/archive/2011/11/25/2262901.html
跟小静读CLR via C#(15)--String,熟悉而又陌生相关推荐
- 跟小静读CLR via C#-开篇及目录
最近正在拜读Jeffrey大师的.NET巨作-<CLR via C#>.好书就像一杯茶,需要静下心来慢慢品.在写笔记的过程中,也加入了自己的思考:在和园友们的交流中,理解也不断的加深. 目 ...
- 跟小静读CLR via C#(02)-基元类型、引用类型、值类型
跟小静读CLR via C#(02)-基元类型.引用类型.值类型 一. 基元类型 编译器能够直接支持的数据类型叫做基元类型.例如int, string等.基元类型和.NET框架类库FCL存在着直接的映 ...
- 跟小静读CLR via C#(05)- 访问限定、数据成员
跟小静读CLR via C#(05)- 访问限定.数据成员 今天跟大家分享一下关于访问限定和数据成员的知识.主要包括以下两点: Abstract, sealed, virtual, new, over ...
- 跟小静读CLR via C#(06)- 构造器
跟小静读CLR via C#(06)- 构造器 最近忙着看新还珠,好几天不学习了.玩物丧志啊,罪过罪过. 今天总结的是类构造器的知识,其实这方面的文章蛮多的,可还是觉得亲自写一下对自己的思考和认识会有 ...
- 跟小静读CLR via C#(16)--泛型
泛型就像是一个模板,常常定义一些通用的算法,具体调用时再替换成实际的数据类型,提高了代码的可重用性. 一.初识泛型 1. 简单实例 以最常用的FCL中的泛型List<T >为例: stat ...
- 跟小静读CLR via C#(10)-参数
最近几天学了参数,其实对于参数本不陌生,从上学学C语言基础的时候就学过了.不过细心学下来,还是收获了一些. 一. 命名参数.可选参数 命名参数和可选参数是在Visual C#2010中引入的新特性. ...
- 跟小静读CLR via C#(18)——Enum
1. Enum定义 枚举类型是经常用的一种"名称/值"的形式,例如: public enum FeedbackStatus { New, ...
- 跟小静学CLR via C#(12)-委托Delegate
本来按照进度应该学习事件了,可总觉得应该委托在前,事件在后,才好理解. 委托是一个类,它提供了回调函数机制,而且是类型安全的.使用委托可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数 ...
- 跟小静读《jQuery权威指南》——目录
前言 2014年开始了,年底给自己制订的学习计划,第一步先从学习<jQuery权威指南>开始. jQuery大家都很比较熟悉,但是我经常是边用的时候边对照着API,这次找本书通读一遍,记录 ...
- android百度地图小人头像怎么做,出包女王村雨静-小静-Murasame Oshizu-头像图片-资料介绍-acg人物点评...
村雨静是动漫<to love>中的登场人物,是四百年前过世的幽灵,进入御门制作的人工身体里转进彩南高中.因为是附身身体,所以经常跌倒,也经常出包的麻烦制造者.一见到最害怕的狗,念力就会失控 ...
最新文章
- pyspark dataframe数据连接(join)、转化为pandas dataframe、基于多个字段删除冗余数据
- 小白都能看懂的目前主流加密MD5验签
- ASP.NET2.0通用数据访问类
- C# DataRow数组转换为DataTable
- 我们应该搞清楚分支预测
- oracle安装 衍生进程已退出,linux安装oracle 出现问题
- 机器人的动力学有什么用呢?
- css不继承上级样式_【FrontEnd】CSS
- mysql数据库隐式表_解析MySQL隐式转换问题
- linux boot efi分区 容量,解决Ubuntu上由于/boot容量不足引起的无法更新系统
- 20个基本电路图讲解_12v太阳能充电电路图大全
- 安装php项目后图片路径不对,解决织梦CMS栏目绑定二级域名后图片不显示,路径错误办法...
- Luogu3941[湖南集训2017] 入阵曲
- iReasoning MIB Browser显示中文乱码问题
- java模板方法模式_Java设计模式之模板方法模式
- MTF 曲线图应该怎么看?
- 大数据常用的开发工具
- 【机器学习】浅谈 归纳偏置 (Inductive Bias)
- 对于API5L管线管的感应圈调控
- 如何在群里引流?如何通过别人的群引流?建一个群怎么快速裂变引流