C#中的字符串
【摘要】通过构造字符串、字符串的不可变性、字符串的留用等几个方面对字符串进行阐述。
【关键词】String;字符串留用;字符串不可变性
在编程时,我们不可避免的要用到字符串,而在C#中,一个String代表一个不可变的顺序字符集。String直接派生自Object,所以它是一个引用类型。因此,String(字符串数组)总是存在于堆上,永远不会存在于栈上。
一、创建字符串
许多编程语言(包括C#)都将String视为一个基元类型,也就是说编译器允许在源代码中直接表示文本常量字符型。编译器将这些文本常量字符串放到模块的元数据中,并在运行时加载和引用它们。在C#中,不能使用new操作符从一个文本常量字符串构造一个String对象,相反,必须使用简化的语法表示: string str=”aaa”;。
C#提供了一些特殊的语法来帮助开发人员在源代码中输入文本常量字符串。对于换行符、回车符和退格这样的特殊字符,C#采用了C/C++的转义机制:包含回车符和换行符的字符串:String s =“Hi\r\nthere”。 但是,一般不建议这么做。因为在不同的平台解释是不同的,推荐使用System.Environment中定义的NewLine属性。NewLine属性是依赖于平台的,他会一句底层平台返回恰当的字符串。最后,C#还提供了一种特殊的字符串声明方式(@”xxx”)。采用这种方式,引号之间的所有字符都会被视为字符串的一部分。这种特殊声明称为”逐字字符串”,通常用于指定文件或目录的路径,或者配合正则表达式使用。
二、字符串是不可变的
String对象最重要的一个事实就是,它是不可变的。也就是说,字符串一经创建就不能更改,不能变长、变短或修改其中任何字符。
字符串不可变也下面几点好处:
1.它允许在字符串上执行任何操作,而不实际的更改字符串。
2.在操作或访问字符串时不会发生线程同步问题。
3.CLR可通过一个String对象共享多个完全一致的String内容。这样能减少系统中的字符串属性,从而节省内存。
考虑到性能方面的原因,String类型和CLR是紧密集成的。具体的说,CLR
知道String类型中定义的字段是如何布局的,而且CLR会直接访问这些字段。但是,为了获得这种性能和直接访问的好处,开发时只好将String定义为密封类。
看下面的例子:
String str1=“a!”;
String str2=str1;
str1=“b!”;
Console.WriteLine(”{0}\n{1}”,str1, str2);
控制台输出结果为: b! a!
字符串对象一旦创建,在整个进程的生命周期中是不可变的,无法对其进行加长、缩短、改变等操作。如果创建了对字符串的引用,然后修改原始字符串,则该引用指向的仍然是原始字符串,而不是修改字符串时创建的新对象。如果要对String进行修改,那么就必须创建一个新的字符串,用<String>. ToCharArray()方法得到字符串的Char数组。对数组进行修改,调用new String(Char [])这个构造函数,来创建Char数组的字符串,一旦字符串被创建,那么Char数组的修改也不会造成字符串的变化。
看下面的例子:
static void Main(string[] args) {
string s1=“hello”;
char[] chars = s1.ToCharArray();
chars[0] = „A‟;
string s2 = new string(chars);
Console.WriteLine(”s1=“+s1.ToString());
Console.WriteLine(”s2=“+s2.ToString());
Console.ReadKey(); }
控制台输出结果:s1=hello s2=Aello
三、字符串的留用
CLR使用“字符串留用”机制来提高性能,CLR初始化时,它会创建一个内部哈希表,在这个哈希表中,key是字符串,value是对托管堆中的string对象的引用。当定义一个string 时,就会在内部哈希表中检查是否有相匹配的。如果不存在完全相同的字符串,就创建字符串副本,将字符串副本添加到内部哈希表中,并返回这个副本的引用。如果存在完全相同的字符串,就返回对现有字符串的引用。
除此之外,如果在内存中复制同一个字符串的多个实例,会造成内存的浪费,因为字符串是”不可变”的。如果只在内存中保留字符串的一个实例,那么将显著提高内存的利用率。需要引用字符串的所有变量只需指向单独一个字符串对象。
如果引用程序经常对字符串进行区分大小写、序号式比较,或者事先知道许多字符串对象都有相同的值,就可以利用CLR的”字符串留用”机制来显著提高性能。CLR初始化时会创建一个内部哈希表。在这个表中,键(key)是字符串,而值(value)是对托管堆中String对象的引用。哈希表最开始是空的,String类提供了两个方法,便于你访问这个内部哈希表:
public static string Intern(string str)
public static string IsInterned (string str)
因篇幅问题不能全部显示,请点此查看更多更全内容