C#struct new StructType()与默认值(StructType)的比较

C#struct new StructType()与默认值(StructType)的比较,c#,struct,C#,Struct,假设我有一个结构 public struct Foo { ... } 两者之间有什么区别吗 Foo foo = new Foo(); 及 ?否,两个表达式将产生相同的精确结果 由于结构不能包含显式无参数构造函数(即,您不能自己定义一个),默认构造函数将为您提供一个所有值均为零的结构版本。这与default提供给您的行为相同。default关键字在您不知道确切类型时非常有用,并且它不仅适用于结构,例如泛型: T FirstOrDefault(IEnumerable<T> s

假设我有一个结构

public struct Foo
{
    ...
}
两者之间有什么区别吗

Foo foo = new Foo();


否,两个表达式将产生相同的精确结果


由于结构不能包含显式无参数构造函数(即,您不能自己定义一个),默认构造函数将为您提供一个所有值均为零的结构版本。这与
default
提供给您的行为相同。

default
关键字在您不知道确切类型时非常有用,并且它不仅适用于结构,例如泛型:

T FirstOrDefault(IEnumerable<T> source)
{
    if (...source is empty...) return default(T);
}
T FirstOrDefault(IEnumerable源代码)
{
如果(…源为空…)返回默认值(T);
}
这将为引用类型返回null,为基元类型返回默认值(0表示数字,false表示bool),默认初始化结构,等等


当类型在编译时已知时,使用
default
是没有意义的,您可以使用
new Foo()
来代替您可能想知道,如果它们完全相同,为什么有两种方法来做相同的事情

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

static T MakeDefault<T>()
{
    return default(T); // legal
    // return new T(); // illegal
}
static T MakeDefault()
{
返回默认值(T);//合法
//返回新的T();//非法
}

语言规范(§4.1.2和§5.2)是您的朋友。具体而言:

对于值类型的变量,默认值与值类型的默认构造函数计算的值相同(§4.1.2)

(原件为斜体。)

请注意,这与引用类型不同

对于引用类型的变量,默认值为
null


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

对于值类型,实际上选项是等效的

然而,我对Jon Skeet的“指令”很感兴趣,因为“指令”导致在CIL中指定结构的无参数默认构造函数时调用它(你不能在C#中这样做,因为它不允许你这样做)。除此之外,他还尝试了
default(T)
newt()
,其中
T
是一个类型参数。它们看起来是等价的;他们似乎都没有调用构造函数

但他似乎没有尝试过的一个案例是
default(Foo)
,其中
Foo
是一个实际案例 结构类型

所以我拿了他的“黑客”结构代码,自己试了试


事实证明,default(Foo)不调用构造函数,而new Foo()实际上调用构造函数。

使用指定无参数构造函数的结构类型
Oddity

static T MakeDefault<T>()
{
    return default(T); // legal
    // return new T(); // illegal
}
关闭优化后,方法:

private void CallDefault()
{
    Oddity a = default(Oddity);
}
private void CallNew()
{
    Oddity b = new Oddity();
}
生成CIL(无
nop
s、
ret
s等):

鉴于该方法:

private void CallDefault()
{
    Oddity a = default(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
中构造函数的调用(是否有潜在的副作用?)

+1我刚才试过,这两个表达式生成相同的IL。如果存在无参数的ctor,则它们生成不同的IL;看我的答案。很有趣,安尼。Jon Skeet的文章说,在使用泛型
default(T)
时,不会调用构造函数。有人知道它在使用非泛型的
默认值(Foo)
时的表现吗?我猜构造函数将由
default(Foo)
@Ani调用:参见规范。它在那里明确地说明了,并在我的中复制了。@Jason:关于规范-使用反射,您实际上可以区分具有默认ctor的结构和不具有默认ctor的结构。因此,在这个级别上,结构甚至可能没有一个ctor。也许规范告诉了我们一个“善意的谎言”?(我所说的可能完全是胡说八道;希望埃里克能澄清)。我不想对利珀特的回答提出质疑,但这里的范围比问题更为广泛;OP特别询问了structs。如果我没有弄错的话,
static T MakeDefault(),其中T:struct{return new T();}
是合法的。。。那么它是不同的吗?@BenMosher:在这种情况下,
new T()
default(T)
是相同的,编译器将为两者生成相同的代码。