C#struct new StructType()vs default(StructType)

时间:2011-02-11 21:07:00

标签: c# struct

说我有一个结构

public struct Foo
{
    ...
}

之间有什么区别吗?
Foo foo = new Foo();

Foo foo = default(Foo);

5 个答案:

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