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)
是相同的,编译器将为两者生成相同的代码。