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 文档 ...
随机推荐
- iOS开发——UI进阶篇(二)自定义等高cell,xib自定义等高的cell,Autolayout布局子控件,团购案例
一.纯代码自定义等高cell 首先创建一个继承UITableViewCell的类@interface XMGTgCell : UITableViewCell在该类中依次做一下操作1.添加子控件 - ( ...
- iOS开发——UI基础-UIScrollView
一.UIScrollView使用的步骤 1.创建UIScrollView 2.将需要展示的内容添加到UIScrollView中 3.设置UIScrollView的滚动范围 (contentSize) ...
- hdu4747——Mex
1.题目大意:对一个序列的每一个区间求Mex,最后所有的mex相加(mex就是SG的那个),力求nlogn... 2.分析:最近开始刷线段树了,还是有很多不会啊 首先把1-1 1-2 1-- 1-n这 ...
- leetcode 100. Same Tree
Given two binary trees, write a function to check if they are equal or not. Two binary trees are con ...
- [KOJ6023]合并果子·改
[COJ6023]合并果子·改 试题描述 在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆.多多把这些果子堆排成一排,然后所有的果子合成一堆. 每一次合并,多多可以 ...
- Oracle 多表查询优化
ORACLE有个高速缓冲的概念,这个高速缓冲就是存放执行过的SQL语句,那oracle在执行sql语句的时候要做很多工作,例如解析sql语句,估算索引利用率,绑定变量,读取数据块等等这些操作.假设高速 ...
- 跟着百度学PHP[2]-foreach条件嵌套
任务 通过二维数组,保存了学号.姓名和成绩,可以通过两个循环嵌套,遍历出学号和姓名. <?php $student = array( '001' => array("王大牛&qu ...
- ReLU 和sigmoid 函数对比以及droupout
参考知乎的讨论:https://www.zhihu.com/question/29021768 1.计算简单,反向传播时涉及除法,sigmod求导要比Relu复杂: 2.对于深层网络,sigmod反向 ...
- Mysql中索引的 创建,查看,删除,修改
创建索引 MySQL创建索引的语法如下: ? 1 2 3 CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name [USING index_type] ON ...
- am335x UART1输入u-boot 调试信息代码修改
AM335x 调试信息UART1输出代码修改1. 关于pin_mux 的配置代码修改位置:/board/forlinx/ok335x/mux.c void enable_uart0_pin_mux( ...

