好久没写文章了,再拿起这本书,学习加分享,乐趣无穷啊。这两天看了写关于字符串的知识,从学写代码的时候开始,我们就基本天天跟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. K-V-O 键值观察机制

    在两个不同的控制器之间传值是iOS开发中常有的情况,应对这种情况呢,有多种的应对办法.kvc就是其中的一种,所以,我们就在此解释之.   key value observing  键值观察,给人一种高 ...

  2. C 语言 homework(2)

    <C语言程序设计>实验报告 学 号 160809215 姓 名 韩笑 专业.班 计科16-2班 学 期 2016-2017 第1学期 指导教师 黄俊莲 吴喆 实验地点 C区二层机房 机 器 ...

  3. python——tuple元组

    >>> dir(tuple) ['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', ...

  4. Objective C 快速入门学习三

    1.数据类型 和C语言基本一样. 有一个特别数据类型id,可以储存任何类型的对象,它是实现多态和动态绑定的基础. Objective-C 2.程序结构 Objective-C和C的程序结构一模一样,具 ...

  5. Unity3D 给模型偏移纹理

    给模型偏移纹理 using UnityEngine; using System.Collections; [RequireComponent(typeof(Renderer))] public cla ...

  6. ios xib 中的 size class

    需要阅读UITraitCollection的说明文档,先截图如下: 今天说说xib中的size class的简单设置,先看图 一共有9个小块,水平方向代表width,垂直方向代表height. 对于w ...

  7. FFMpeg ver 20160213-git-588e2e3 滤镜中英文对照

    1 FFMpeg ver 20160213-git-588e2e3 滤镜中英文对照 2016.02.18 by 1CM 2 T.. = Timeline support 3 支持时间轴 4 .S. = ...

  8. Java for LeetCode 232 Implement Queue using Stacks

    Stack<Integer> stack=new Stack<Integer>(); public void push(int x) { stack.push(x); } // ...

  9. vps mysql自动关闭

    买了个阿里云的vps 装了一个wordpress,mysql一直自动关闭,百思不得其解,只有搜索 最后才发现是因为服务器内存太小,毕竟是最便宜的才512m ---------------------- ...

  10. codeforces 495A. Digital Counter 解题报告

    题目链接:http://codeforces.com/problemset/problem/495/A 这个题目意思好绕好绕~~好绕~~~~~,昨天早上做得 virtual 看不懂,晚上继续看还是,差 ...