字符串是值类型还是引用类型?
我就是找不到一个“好”的解释……
Console.WriteLine(typeof(string).IsClass); // true
这是一个引用类型。
它不能是值类型,因为值类型需要在堆栈等地方有已知的大小。作为引用类型,即使字符串的大小未知,引用 的大小也是预先已知的。
由于它是不可变的,所以它的行为类似于你期望的值类型; 即一旦创建就不会更改。但是还有很多其他不可变的引用类型。例如Delegate实例。
* = 除了在 StringBuilder
内部,但在此期间您从未看到它…
string
的默认值是 null
,这是因为 string
是一个引用类型。说 string
的默认值是 ""
是不正确的,因为它并不是。 - Marc Gravell基本的“解释”是基于在“声明”变量时分配给这个变量的内存位置中实际存储的“内容”。“值类型”指的是如果该变量名所引用的内存位置中存储了该内容的实际值。
int x; // memory allocated to hold Value of x, default value assigned of zero
如果在“声明”变量时分配的内存槽只会保存一些其他内存地址,实际值(或值)将存储在那里,那么它就是引用类型。
MyClass x; // Memory allocated to hold an address,
// default address of null (0) assigned.
// NO MEMORY ALLOCATED for x itself
或者,如果声明包括初始化:
MyClass x = new MyClass();
// Now, Memory slot (call it Addr1) is allocated to hold address of x,
// more memory (call it Addr2) is allocated to hold a new MyClass object.
// New MyClass object created, stored in memory Addr2 (on the Heap)
// Address of new object (Addr2) is stored in Addr1
对于一个字符串,它是在堆上创建的,它的地址存储在为变量分配的内存空间中,因此它是一种引用类型。
字符串是一种不可变的引用类型,具有某些特性,使其偶尔表现出值类型的外观。
字符串类型代表了零个或多个Unicode字符的序列。在.NET Framework中,string是String的别名。
尽管string是引用类型,但相等运算符(==和!=)被定义为比较string对象的值而不是引用。这使得测试字符串相等更加直观。例如:
string a = "hello";
string b = "h";
// Append to contents of 'b'
b += "ello";
Console.WriteLine(a == b);
Console.WriteLine((object)a == (object)b);
这段代码输出"True",然后是"False",因为字符串的内容相同,但a和b并不引用同一个字符串实例。
字符串是不可变的--在创建字符串对象之后,无法更改其内容,尽管语法似乎可以这样做。例如,当您编写此代码时,编译器实际上会创建一个新的字符串对象来保存新字符序列,并将该新对象分配给b。然后,字符串"h"就可以被垃圾回收了。
string b = "h";
b += "ello";
NullReferenceException
:string s0 = null; Console.WriteLine(s0); string result = String.Concat(s0, "aaa");
也许它只是不太适合被承认的类别中。 - H2ONaClArgumentNullException
,但是两种方法都明确表示他们不选择这样做;Console.WriteLine
说:“如果值为null,则仅将行终止符写入标准输出流。”;String.Concat
说“空字符串用于替换任何空参数。”。这很好。我们通常期望NullReferenceException
的唯一时间是像s0.Length
这样的东西,它确实会抛出异常。 - Marc Gravell