我最近碰到谁提到的,我们不应该初始化类变量...如果我们要使用默认值进行初始化有人来了。
我同意,但是......
是否有任何这方面的实际性能提升?
不,这是完全一样的。不同之处仅在于风格。
让我们仔细看看。让我们听听你的类的变异不设置你的标志,它初始化为默认,初始化它,否则,并且在构造函数一举两得:
public class NoInit
{
private bool _flag;
}
public class DefaultInit
{
private bool _flag = false;
}
public class NonDefaultInit
{
private bool _flag = true;
}
public class TestDefaultCtor
{
private bool _flag;
public TestDefaultCtor()
{
_flag = false;
}
}
public class TestNonDefaultCtor
{
private bool _flag;
public TestNonDefaultCtor()
{
_flag = true;
}
}
现在让我们编译发布版本:
.class public auto ansi beforefieldinit NoInit
extends [mscorlib] System.Object
{
.field private bool _flag
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib] System.Object::.ctor()
IL_0006: ret
}
}
.class public auto ansi beforefieldinit DefaultInit
extends [mscorlib] System.Object
{
.field private bool _flag
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib] System.Object::.ctor()
IL_0006: ret
}
}
.class public auto ansi beforefieldinit NonDefaultInit
extends [mscorlib] System.Object
{
.field private bool _flag
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldc.i4.1
IL_0002: stfld bool NonDefaultInit::_flag
IL_0007: ldarg.0
IL_0008: call instance void [mscorlib] System.Object::.ctor()
IL_000d: ret
}
}
.class public auto ansi beforefieldinit TestDefaultCtor
extends [mscorlib]System.Object
{
.field private bool _flag
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ldarg.0
IL_0007: ldc.i4.0
IL_0008: stfld bool TestDefaultCtor::_flag
IL_000d: ret
}
}
.class public auto ansi beforefieldinit TestNonDefaultCtor
extends [mscorlib]System.Object
{
.field private bool _flag
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ldarg.0
IL_0007: ldc.i4.1
IL_0008: stfld bool TestNonDefaultCtor::_flag
IL_000d: ret
}
}
正如你所看到的,而标志设置为true有效果(当然,它有什么地方发生),并在构造函数中设置它确实导致设置为false明确地编译(不过,这并不一定意味着有是否有任何差异一旦jitted)之间,DefaultInit
和NoInit
之间是什么它没有什么区别mpiled to。如果我们要将它反编译回C#,我们必须自己调用,以明确地将其设置为false,否则就像在首先编写它时一样。
因此,就结果而言,两者完全相同。
这不赚取差价完全不重要。 (以为我宁愿一个我正在研究的项目一直使用我不喜欢的方法,而不是很不一致;不一致性更差)。
但是,很多初始化可能有点繁忙,并且不会向足够经验的编码人员添加任何信息*以知道什么类型的默认值,并且在我们初始化为特定值时出于某种原因使其更清晰。
如果我们打算(或有时会)在构造函数中设置值,它也可能看起来特别多余。 (虽然注意,初始化为默认值,然后在构造函数中进行设置的编译与在构造函数中设置没有什么不同,但如果我们初始化为非默认值,那么在jitting时通常会将其优化掉,但这并不正确。并不总是,特别是当初始化有副作用时)。
在调试会话期间,它还可能导致较低的信噪比,从而产生大量无趣的初始化。
所以,我认为编码约定是有道理的,我同意你提到的那些人会有什么约定,但他们是约定,而不是影响性能的东西。
*相比之下使用private
或internal
其中那些预设至少增加了一个无论是在分别的一类或命名空间上下文信息(分别是什么使这些默认值,]),所以它是一个小东西更少让读者去思考。所以我更喜欢这是明确的。
运行代码并*找出*。 – Servy
该链接仅讨论'new int()'与初始化为'0'相同,但没有关于*不初始化*变量。 – crashmstr
@crashmstr:我认为OP使用该页面作为默认值的参考,而不是断言的来源。也就是说,“我的朋友说我们不应该将变量初始化为默认值[这里](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/default-values-表)。” –