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#(15)--String,熟悉而又陌生的更多相关文章
- 2017.11.15 String、StringBuffer、StringBuilder的比较(todo)
参考来自:http://blog.csdn.net/jeffleo/article/details/52194433 1.速度 一般来说,三者的速度是:StringBuilder > Strin ...
- [CLR via C#]15. 枚举类型和位标志
一.枚举类型 枚举类型(enumerated types)定义了一组"符号名称/值"配对. 例如,以下Color类型定义了一组符号,每个符号都标识一种颜色: internal en ...
- 【CLR】奇妙的String
- 一.背景 1. 以下代码的HashCode是否相同,它们是否是同个对象: var A = "ab" + "c"; var B = "abc&quo ...
- 【Java面试题】15 String s="Hello"; s=s+“world!”;这两行代码执行后,原始的String对象中的内容到底变了没有?String与StringBuffer的超详细讲解!!!!!
1.Java中哪些类是不能被继承的? 不能被继承的是那些用final关键字修饰的类.一般比较基本的类型或防止扩展类无意间破坏原来方法的实现的类型都应该是final的,在java中,System,Str ...
- Android探索之ContentProvider熟悉而又陌生的组件
前言: 总结这篇文章之前我们先来回顾一下Android Sqlite数据库,参考文章:http://www.cnblogs.com/whoislcj/p/5506294.html,Android程序内 ...
- LINQ to SQL语句(15)之String
LINQ to SQL支持以下String方法.但是不同的是默认情况下System.String方法区分大小写.而SQL则不区分大小写. 1.字符串串联(String Concatenation) v ...
- String的内存模型,为什么String被设计成不可变的
String是Java中最常用的类,是不可变的(Immutable), 那么String是如何实现Immutable呢,String为什么要设计成不可变呢? 前言 关于String,收集一波基础,来源 ...
- 字符、字符串和文本的处理之String类型
.Net Framework中处理字符和字符串的主要有以下这么几个类: (1).System.Char类 一基础字符串处理类 (2).System.String类 一处理不可变的字符串(一经创建,字符 ...
- LINQ体验(11)——LINQ to SQL语句之Null语义和String/DateTime方法
在本系列中.主要介绍LINQ to SQL基础的东西,由于LINQ太强大了,它对我们寻常使用不同的数据源有着不同的内容,其包含对于SQL Server 数据库的LINQ to SQL:对于XML 文档 ...
随机推荐
- Unity手游之路<十>自动寻路Navmesh之跳跃,攀爬,斜坡
http://blog.csdn.net/janeky/article/details/17598113 在之前的几篇Blog总,我们已经系统学习了自动寻路插件Navmesh的相关概念和细节.然而,如 ...
- C#字符串和数据之间的转换
c#中不仅仅存在数值类型的数据之间的转换,字符串和数值之间也是可以互相转换的,只是方法不同而已. 1 数值型转换为字符型 数值型数据转换为字符串用ToString()方法即可实现 int num1=1 ...
- OpenCv haar+SVM训练的xml检测人头位置
注意:opencv-2.4.10 #include "stdio.h"#include "string.h"#include "iostream&qu ...
- 40 网络相关函数(八)——live555源码阅读(四)网络
40 网络相关函数(八)——live555源码阅读(四)网络 40 网络相关函数(八)——live555源码阅读(四)网络 简介 15)writeSocket向套接口写数据 TTL的概念 函数send ...
- Jenkins 报错:(pending—Waiting for next available executor)
系统管理-管理节点,刷新状态
- IDEA 新建文件默认加入CVS
是要先add,不过可以设置创建的文件都默认 add的.修改默认值看下图:打开系统设置,找到 Version Control 设置选项: 在 When files are created 选项中选择第二 ...
- ITIL与ITSM的联系与区别
1.ITIL(IT Infrastructure Library)是CCTA(英国国家计算机和电信局)于20世纪80年代末开发的一套IT服务管理标准库,它把英国各个行业在IT管理方面的最佳实践归纳起来 ...
- git stash简介
原文:http://gitbook.liuhui998.com/4_5.html 一.基本操作 当你正在做一项复杂的工作时, 发现了一个和当前工作不相关但是又很讨厌的bug. 你这时想先修复bug再做 ...
- git rebase简介(高级篇)
原文:http://gitbook.liuhui998.com/4_3.html 一.基本 对于git rebase,你亦可以选择进行交互式的rebase.这种方法通常用于在向别处推送提交之前对它 ...
- (转) 站在C#和JS的角度细谈函数式编程与闭包
1.函数式编程是什么? 摘自百度的说法是.函数式编程是种编程典范,它将电脑运算视为函数的计算.函数编程语言最重要的基础是 λ 演算(lambda calculus).而且λ演算的函数可以接受函数当作输 ...

