来自Pro C#
参考“新的”内在数据类型......
所有内部数据类型都支持所谓的默认构造函数。它允许您使用new关键字创建变量。
[...]对象引用(包括字符串)设置为null。
在C#中,字符串没有公共默认构造函数。我的猜测是,由于字符串的不变性,它们有一个私有的默认构造函数。但是,这里的上下文是在使用new
时将对象引用和字符串作为一个整体来讨论。
因为一个人无法做到
String myString = new String();
所以,
String a;
引用字符串不会产生“默认值”。相反,访问。
是一个编译器错误虽然
public class StringContainer
{
public static string myString { get; set; }
}
以合法可访问的字符串形式生成(默认为null)。这不使用new
。它执行某种神奇的构造。
StringContainer
场景中发生了什么?因为字符串中似乎没有新的默认构造函数,这是C#book中的错误吗?
答案 0 :(得分:18)
所有内部数据类型都支持所谓的默认构造函数。它允许您使用new关键字创建变量。
该陈述中有许多微妙的错误。
首先,没有“内在”数据类型;也许这个术语在本书的其他地方定义了?
其次,更准确地说所有 struct 类型都有一个名为“default”构造函数的公共无参数构造函数。一些类类型也有一个公共无参数ctor;如果你不提供任何ctor,那么C#编译器将自动为你生成一个公共无参数ctor。如果您确实提供了ctor,那么C#编译器将不会为您执行此操作。
第三,构造函数不会创建变量。作者正在混淆一堆相关但不同的东西:“新”运算符,内存管理器,构造函数和变量,以及创建的对象。变量是存储位置,由CLR管理;它们不是由“new”运算符创建的。
正确的说法是结构上的“new”运算符导致临时存储池上的CLR 创建一个变量;然后,该变量由内存管理器初始化,然后传递给构造函数以进行更多初始化。这样创建的值然后在其他地方复制。类上的“new”运算符会导致CLR在长期存储池上创建对象,然后将引用传递给该对象到CLR。不需要涉及“变量”。
将变量与对象混淆是一个非常常见的错误;理解差异是很有价值的。
在C#中,字符串没有公共默认构造函数。
正确。
我的猜测是,由于字符串的不变性,它们有一个私有的默认构造函数。
好猜,但错了。字符串上没有私有的无参数构造函数。
[自动属性或字符串类型的字段]导致合法可访问的字符串(默认为null)。这不使用新的。它执行某种神奇的构造。
没有这样的事情。空引用根本不是构造对象。这是没有构造对象!
你基本上说我的空车库包含一辆“神奇构造”的不存在的汽车。看一个空车库,这是一种非常奇怪的方式;一个空车库根本没有车,不是一辆神奇的不存在的车。
StringContainer scenerio中发生了什么?
包含类型包含编译器生成的字段 - 变量 - 类型为字符串。我们假设包含类型是结构或类。当内存管理器初始化结构或类的存储时,内存管理器将空引用写入与该变量关联的存储位置。
最后:我怀疑你的困惑是因为你已经得到了“默认构造函数”并且“类型的默认值”混淆了。对于结构体,它们是相同的:
int x = new int();
和
int x = default(int);
将int初始化为零。
对于一个班级,他们不会做同样的事情:
Fruit f = new Fruit();
创建一个新的水果引用并将引用分配给变量f,而:
Fruit f = default(Fruit);
与
相同Fruit f = null;
没有调用构造函数。
答案 1 :(得分:5)
所有内部数据类型都支持所谓的默认构造函数。它允许您使用new关键字创建变量。
我不确定作者的“内在数据类型”是什么意思。我最好的猜测是他实际上意味着“值类型”(即用C#的struct
关键字声明的类型),因为值类型总是有一个默认的构造函数,而引用类型可能没有。
因此,如果您有一个类型为struct
类型的字段(例如Int32,CancellationToken),那么该字段将被初始化,就像调用类型的默认构造函数一样。
在实际实现中,可能没有对类型的默认构造函数进行实际调用 - 内存只是初始化为全零,这与执行的操作相同调用默认构造函数。 (这就是为什么你不能为值类型提供自己的无参数构造函数 - 无参数构造函数总是将内存初始化为全零。这大大简化了new int[10000]
之类的东西 - 编译器实际上不需要调用new Int32()
10,000次;它只是将内存清零。)
关于string
中class
字段的问题与作者对“内部数据类型”的讨论并不真正相关,因为string
和您的class
是引用类型,而不是值类型。所以你的类不会有一个无参数构造函数 - 你不能覆盖;它只有普通的构造函数。但是归零行为仍然存在:当你调用构造函数时,新的内存块在构造函数代码开始运行之前被清零。您的string
字段是引用类型,零引用是null
。
答案 2 :(得分:2)
我想它是使用default(string)返回null,因为string是引用类型。
另外,请记住构造函数不能返回null。