C#结构新的StructType()与默认(StructType)

说我有一个结构

public struct Foo { ... } 

有什么区别吗?

 Foo foo = new Foo(); 

 Foo foo = default(Foo); 

你可能想知道为什么,如果它们完全一样,有两种方法可以做同样的事情。

它们不完全相同,因为每个引用types或值types都保证有一个默认值,但并不是每个引用types都保证有一个无参数的构造函数:

 static T MakeDefault<T>() { return default(T); // legal // return new T(); // illegal } 

不,这两个expression式都会产生相同的结果。

由于结构体不能包含显式的无参数构造函数(也就是说你不能自己定义一个构造函数),所以默认的构造函数会给你一个所有值为零的结构体的版本。 这是default给你的同样的行为。

对于价值types来说,这些选项实际上是等价的。

然而,我对Jon Skeet的经验研究很感兴趣,在CIL中指定的时候,“指令”会导致调用struct的无参数默认构造函数(因为它不允许你这样做)。 除此之外,他尝试了default(T)new T() ,其中T是一个types参数。 他们似乎相当; 他们两个都没有打电话给build设者。

但是,他没有尝试过的一种情况(看起来)是default(Foo) ,其中Foo是一个实际的结构types。

所以我把他的代码用于“黑客”的结构,并为自己尝试了一下。


事实certificate,默认(Foo)不调用构造函数,而新的Foo()实际上是这样做的。

使用指定无参数构造函数的struct type Oddity

closures优化后 ,方法:

 private void CallDefault() { Oddity a = default(Oddity); } 

产生CIL(没有nop s, ret s等):

 L_0001: ldloca.sa L_0003: initobj [Oddity]Oddity 

而方法:

 private void CallNew() { Oddity b = new Oddity(); } 

生产:

 L_0001: ldloca.sb L_0003: call instance void [Oddity]Oddity::.ctor() 

在开启优化的情况下 ,编译器似乎将几乎所有CallDefault方法优化成一个no-op,但保持CallNew构造函数的CallNew (对于潜在的副作用?)。

语言规范(§4.1.2和§5.2)是你的朋友。 特别:

对于一个值types的variables,默认值与值types的默认构造函数(§4.1.2)计算的相同。

(原始斜体)

请注意,这与参考types不同。

对于引用types的variables,默认值为null

这与默认构造函数产生的值(如果存在的话)有着明显的不同。

default关键字是非常有用的,当你不知道确切的types,它不仅适用于结构,例如在generics:

 T FirstOrDefault(IEnumerable<T> source) { if (...source is empty...) return default(T); } 

这将返回null为参考types,基元types的默认值(0为数字,为布尔假),默认为初始化结构等…

在编译时知道types是没有意义的,你可以使用new Foo()来代替