关于C#中的类型
在C#中类型分为值类型和引用类型,引用类型和值类型都继承自System.Object类,几乎所有的引用类型都直接从System.Object继承,而值类型具体一点则继承System.Object的子类,即继承System.ValueType。而String类型却有点特别,虽然它属于引用类型,但是他的一些特性却有点类似值类型。
关于C# String 1、不变性我们先来看看一个例子:
static void Main(string[] args) { string str1 = "string"; string str2 = str1; Console.WriteLine(object.ReferenceEquals(str1, str2)); str2 += "change"; Console.WriteLine(object.ReferenceEquals(str1, str2)); Console.ReadKey(); }输出结果是True、False。为什么呢?我们来看看IL。
.entrypoint // 代码大小 48 (0x30) .maxstack 2 .locals init ([0] string str1, [1] string str2) IL_0000: nop IL_0001: ldstr "string" IL_0006: stloc.0 IL_0007: ldloc.0 IL_0008: stloc.1 IL_0009: ldloc.0 IL_000a: ldloc.1 IL_000b: ceq IL_000d: call void [mscorlib]System.Console::WriteLine(bool) IL_0012: nop IL_0013: ldloc.1 IL_0014: ldstr "change" IL_0019: call string [mscorlib]System.String::Concat(string,string) IL_001e: stloc.1 IL_001f: ldloc.0 IL_0020: ldloc.1 IL_0021: ceq IL_0023: call void [mscorlib]System.Console::WriteLine(bool) IL_0028: nop IL_0029: call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey() IL_002e: pop IL_002f: ret+=在内部调用了Concat函数,将str2和"change"连接起来直接生成了一个新的字符串,和原来的字符串是不同的对象。Trim、Remove函数都是会直接生成一个新的对象,字符串一经定义,就不能改变。
其实字符串具有原子性(也就是不变性),任何改变字符串的值的行为都不会成功,只会创建一个新的字符串对象。在实际编程中,我们会大量的使用字符串,这样就会导致不停地创建新的字符串对象和分配内存,可能导致垃圾回收器GC不停地进行垃圾回收,大大降低性能,并且伴随着内存溢出的危险。所以.Net对字符串进行了的特殊的处理,这就是字符串驻留池。
在字符串驻留池,保存着字符串字面值和指向的引用。每次有新的字符串创建,都会在驻留池中查找是否存在字面值相同的字符串,如果存在就将其指向已经存在的字符串的引用,不存在就直接新建一个字符串,然后指向一个新的地址。
2、作为函数参数的处理在函数的参数传递中,值类型直接拷贝变量保存的值,传递的是一个值得副本,而引用类型传递的是地址的一个副本,所以在函数中改变引用参数中属性的值会直接改变函数外真实类型对象的值。
static void Main(string[] args) { People people = new People() { Name = "Jack" }; Console.WriteLine(people.Name); Change(people); Console.WriteLine(people.Name); Console.ReadKey(); } static void Change(People p) { p.Name = "Eason"; } class People { public string Name { get; set; } }程序先输出Jack,后输出Eason,可以说明引用类型传递的是引用地址,函数改变的参数对象和外部传递进来的对象是一个对象。
那么我们来看看String作为参数的情况:
static void Main(string[] args) { string str = "string"; Console.WriteLine(str); Change(str); Console.WriteLine(str); Console.ReadKey(); } static void Change(string str) { str = "change"; Console.WriteLine(str); }结果输出string、change、string。调用Change函数后str的值还是"string",由于字符串类型的不变性,在Change函数中对str进行赋值会重新创建一个新的字符串对象,然后为这个新的对象附上引用。所以虽然字符串类型是引用类型,但是在参数传递时它其实相当于值类型。
3、相等比较处理