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()
来代替