新的字符串类型

时间:2011-12-19 16:53:38

标签: c#

来自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中的错误吗?

3 个答案:

答案 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次;它只是将内存清零。)

关于stringclass字段的问题与作者对“内部数据类型”的讨论并不真正相关,因为string和您的class是引用类型,而不是值类型。所以你的类不会有一个无参数构造函数 - 你不能覆盖;它只有普通的构造函数。但是归零行为仍然存在:当你调用构造函数时,新的内存块在构造函数代码开始运行之前被清零。您的string字段是引用类型,零引用是null

答案 2 :(得分:2)

我想它是使用default(string)返回null,因为string是引用类型。

另外,请记住构造函数不能返回null。