说我有一个结构
public struct Foo
{
...
}
Run Code Online (Sandbox Code Playgroud)
两者之间有什么区别吗?
Foo foo = new Foo();
Run Code Online (Sandbox Code Playgroud)
和
Foo foo = default(Foo);
Run Code Online (Sandbox Code Playgroud)
?
Eri*_*ert 71
您可能想知道为什么,如果它们完全相同,有两种方法可以做同样的事情.
它们并不完全相同,因为每个引用类型或值类型都保证具有默认值,但并不是每个引用类型都保证具有无参数构造函数:
static T MakeDefault<T>()
{
return default(T); // legal
// return new T(); // illegal
}
Run Code Online (Sandbox Code Playgroud)
And*_*are 17
不,两个表达式都会产生相同的结果.
由于结构不能包含显式无参数构造函数(即您不能自己定义),默认构造函数将为您提供结构的版本,其中所有值都为零.这也是同样的行为default
.
Ani*_*Ani 14
对于价值类型,实际上,这些选项是 等价的.
然而,我对Jon Skeet的实证研究很感兴趣,当在CIL中指定时,'指令'会导致调用struct的无参数默认构造函数(你不能在C#中这样做,因为它不会让你).除此之外,他还试过了default(T)
,类型参数new T()
在哪里T
.它们似乎相同; 他们似乎都没有打电话给构造函数.
但一个情况下(似乎)他没有试图为 default(Foo)
那里Foo
是一个实际的结构类型.
所以我把他的代码用于'黑客'结构并为我自己尝试了.
事实证明,默认(Foo)不会调用构造函数,而新的Foo()实际上就是这样.
使用Oddity
指定无参数构造函数的结构类型:
关闭优化后,方法:
private void CallDefault()
{
Oddity a = default(Oddity);
}
Run Code Online (Sandbox Code Playgroud)
产生CIL(没有nop
s,ret
s等):
L_0001: ldloca.s a
L_0003: initobj [Oddity]Oddity
Run Code Online (Sandbox Code Playgroud)
而方法:
private void CallNew()
{
Oddity b = new Oddity();
}
Run Code Online (Sandbox Code Playgroud)
生产:
L_0001: ldloca.s b
L_0003: call instance void [Oddity]Oddity::.ctor()
Run Code Online (Sandbox Code Playgroud)
随着优化开启,编译器似乎非常优化掉所有的的CallDefault
方法为无操作,但保持在调用构造函数CallNew
(潜在的副作用?).
jas*_*son 12
语言规范(§4.1.2和§5.2)是你的朋友.特别:
对于value-type的变量,默认值与value-type的默认构造函数(第4.1.2节)计算的值相同.
(斜体字原文.)
请注意,这与引用类型不同.
对于reference-type的变量,默认值为
null
.
这与默认构造函数(如果存在)生成的值明显不同.
default
当您不知道确切的类型时,关键字非常有用,它不仅适用于结构,例如泛型:
T FirstOrDefault(IEnumerable<T> source)
{
if (...source is empty...) return default(T);
}
Run Code Online (Sandbox Code Playgroud)
这将为引用类型返回null,为基本类型返回默认值(0表示数字,false表示bool),默认为inialized结构等...
当类型是在编译时知道这是没有意义的使用default
,就可以使用new Foo()
,而不是