说我有一个结构
public struct Foo
{
...
}
之间有什么区别吗?
Foo foo = new Foo();
和
Foo foo = default(Foo);
答案 0 :(得分:69)
你可能想知道为什么,如果它们完全相同,有两种方法可以做同样的事情。
它们不完全相同,因为每个引用类型或值类型都保证具有默认值,但不是每个引用类型都保证具有无参数构造函数:
static T MakeDefault<T>()
{
return default(T); // legal
// return new T(); // illegal
}
答案 1 :(得分:17)
不,两个表达式都会产生相同的结果。
由于结构不能包含显式无参数构造函数(即你不能自己定义),默认构造函数会给你一个版本的结构,所有的值都为零。这与default
给你的行为相同。
答案 2 :(得分:14)
对于值类型,选项是,实际上说,等价。
然而,我对Jon Skeet的empirical research很感兴趣,当CIL中指定了一个结构的无参数默认构造函数时,'指令'会导致调用它(你不能在C#中执行它因为它没有'让你)。除此之外,他还尝试了default(T)
和new T()
,其中T
是一个类型参数。它们似乎相同;他们似乎都没有打电话给建设者。
但是他没有尝试过的一个案例(看来似乎)是default(Foo)
,其中Foo
是实际的
结构类型。
所以我把他的代码用于'黑客'结构并为我自己尝试了。
事实证明,默认(Foo)不会调用构造函数,而新的Foo()实际上会调用。
使用指定无参数构造函数的结构类型Oddity
:
关闭优化,方法为:
private void CallDefault()
{
Oddity a = default(Oddity);
}
生成CIL(没有nop
s,ret
等。)
L_0001: ldloca.s a
L_0003: initobj [Oddity]Oddity
而方法:
private void CallNew()
{
Oddity b = new Oddity();
}
产生
L_0001: ldloca.s b
L_0003: call instance void [Oddity]Oddity::.ctor()
启用优化后,编译器似乎将CallDefault
方法的所有优化为no-op,但保持不变 CallNew
中对构造函数的调用(对于潜在的副作用?)。
答案 3 :(得分:12)
语言规范(§4.1.2和§5.2)是你的朋友。具体做法是:
对于 value-type 的变量,默认值与 value-type 的默认构造函数计算的值相同(§4.1.2 )。
(斜体原文。)
请注意,这与参考类型不同。
对于reference-type的变量,默认值为
null
。
这与默认构造函数(如果存在)生成的值明显不同。
答案 4 :(得分:5)
default
关键字很有用,它不仅适用于结构,例如泛型:
T FirstOrDefault(IEnumerable<T> source)
{
if (...source is empty...) return default(T);
}
这将为引用类型返回null,为基本类型返回默认值(0表示数字,false表示bool),默认为inialized结构等...
如果在编译时已知类型,则使用default
没有意义,您可以使用new Foo()
代替