CLR-via-CSharp-07 基本类型

字符

首先在C#中,所有的char都是16bit的unicode字符。

另外,介绍了System.Char类型的一些静态方法和实例方法。

静态方法包括了一个可以从UInt32转成两个Char的方法,名为Char.GetNumericValue()

String

String直接继承于Object,是个引用类型的封闭类,它的对象永远都在堆上,不会出现在线程栈上。

构造字符串

string被C#视为基元类型,不能用new操作符构造,必须使用简化语法:

1
2
3
4
5
6
7
8
9
class Program
{
static void Main(string[] args)
{
String s = "Hello World";
Console.WriteLine();
Console.ReadLine();
}
}

反编译得到IL代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
.method private hidebysig static void  Main(string[] args) cil managed
{
.entrypoint
// Code size 20 (0x14)
.maxstack 1
.locals init ([0] string s)
IL_0000: nop
IL_0001: ldstr "Hello World"
IL_0006: stloc.0
IL_0007: call void [mscorlib]System.Console::WriteLine()
IL_000c: nop
IL_000d: call string [mscorlib]System.Console::ReadLine()
IL_0012: pop
IL_0013: ret
} // end of method Program::Main

可以看到虽然string是一个object,但是生成新对象的时候用的不是newobj命令,而是ldstr(load string)命令。

我们还可以用多个字面值(就是不要用变量的意思)来构造一个字符串,编译器生成IL代码的时候就会把字面值都组合在一起。

逐字字符串

@号加在字符串前面,完全不考虑任何转移符,一般用来指定路径或者用在正则表达式中。

字符串是不可变的(immutable)

字符串一经创建,就不可以再更改。

使用EndsWith()Substring()之类的方法返回的字符串如果没有被引用到,会再后面被GC掉。

字符串不可变,意味着在操作或访问字符串的时候不会发生线程同步问题。CLR可以通过一个String对象共享多个完全一致的String内容,减少系统中的字符串数量,从而减少内存,这个叫做字符串驻留(string interning)。

字符串的比较

字符串的比较建议使用String类的静态方法

1
static Int32 Compare(String strA, String strB, StringComparison comparisonType)

Compare方法有多个重载方法,可以自己查一下api文档,有一些选项可以定制比较的规矩。

注意,执行序号(ordinal)相等性检查时,CLR会先检测两个字符串是否包含相同数量的字符,如果不一样直接就返回false了。但是执行对语言文化敏感比较时,CLR会检查所有字符。

字符串驻留

由于字符串是不可变的,所以内存中只会保留字符串的一个实例,引用字符串的所有变量都会指向单独的同一个的字符串对象。

CLR初始化时会创建一个内部哈希表,一开始是空的。key是字符串,value是对托管堆中的String对象的引用。

String类提供了两个静态方法,可以让你访问这个内部哈希表。

1
public static String Intern(String str);

这个方法根据传进来的参数计算其哈希码,并检查在内部哈希表中是否存在该字符串,有则直接返回引用,没有的话先创建字符串的副本,然后添加到内部哈希表中,再返回对该副本的引用。如果原始的,作为参数传进来那个字符串再也没人引用,有可能就会被GC回收掉,但是被添加到内部哈希表中的字符串,GC再也管不着了,永远被留下来(为什么?没有什么特别的机制,因为这些字符串被内部哈希表引用着呢)。

1
public static String IsInterned(String str);

和上面一个方法类似,只是如果发现哈希表里没有这个字符串,会直接返回null,不会将字符串添加到哈希表中。

注意,虽然上面说到了内存中只会保留字符串的一个实例,但是不意味着每个版本的CLR都是这样的。

Buy Me A Coffee / 捐一杯咖啡的钱
分享这篇文章~
0%
//