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