2017-08-25 64 views
-1

我最近发现有人提到我们不应该初始化类变量(值从https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/default-values-table),如果我们要用默认值初始化它。 这听起来很不对劲。这有什么实际的表现吗? 在下面的例子中,他不想最初将标志设置为假(尽管假设它假设为假)。对类变量使用默认值而不是在c#中初始化它会有什么性能影响吗?

Class Test { 
    private bool flag; 
    private int CheckValue() 
    { 
      if(flag) return 0; 
      else return 1; 
    } 
    private void SetFlag() 
    { 
     flag = true; 
    } 
} 
+4

运行代码并*找出*。 – Servy

+0

该链接仅讨论'new int()'与初始化为'0'相同,但没有关于*不初始化*变量。 – crashmstr

+0

@crashmstr:我认为OP使用该页面作为默认值的参考,而不是断言的来源。也就是说,“我的朋友说我们不应该将变量初始化为默认值[这里](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/default-values-表)。” –

回答

0

C#不允许使用未定义的变量。 CLR仍然初始化为默认值。不设置一个变量时可能接进能够使这个-将待设置后断言由编译器

OTOH检查,字段没有这样的检查。将默认值设置为默认值时,这可能会导致调试器逐步将所有这些字段设置为默认值。就不一一说明可以有生活质量改善WRT调试经验

+1

'C#不允许使用未定义的变量.'这是不正确的。 *某些*变量需要初始化(即当地人),但不是全部。 – Servy

+0

下面是一个很好的答案,为什么不允许本地人未定义,但类变量是:https://stackoverflow.com/a/30820127/2193107它主要与检测某些东西是否实际未分配的复杂性有关。 – JBC

0

在你已经确定你指的是一个布尔字段,它是在幕后的值对象,不能为空的情况。它默认设置为“false”。

一个bool变量的默认值是false。

Source : docs.microsoft.com

0

我最近碰到谁提到的,我们不应该初始化类变量...如果我们要使用默认值进行初始化有人来了。

我同意,但是......

是否有任何这方面的实际性能提升?

不,这是完全一样的。不同之处仅在于风格。

让我们仔细看看。让我们听听你的类的变异不设置你的标志,它初始化为默认,初始化它,否则,并且在构造函数一举两得:

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)之间,DefaultInitNoInit之间是什么它没有什么区别mpiled to。如果我们要将它反编译回C#,我们必须自己调用,以明确地将其设置为false,否则就像在首先编写它时一样。

因此,就结果而言,两者完全相同。

这不赚取差价完全不重要。 (以为我宁愿一个我正在研究的项目一直使用我不喜欢的方法,而不是很不一致;不一致性更差)。

但是,很多初始化可能有点繁忙,并且不会向足够经验的编码人员添加任何信息*以知道什么类型的默认值,并且在我们初始化为特定值时出于某种原因使其更清晰。

如果我们打算(或有时会)在构造函数中设置值,它也可能看起来特别多余。 (虽然注意,初始化为默认值,然后在构造函数中进行设置的编译与在构造函数中设置没有什么不同,但如果我们初始化为非默认值,那么在jitting时通常会将其优化掉,但这并不正确。并不总是,特别是当初始化有副作用时)。

在调试会话期间,它还可能导致较低的信噪比,从而产生大量无趣的初始化。

所以,我认为编码约定是有道理的,我同意你提到的那些人会有什么约定,但他们是约定,而不是影响性能的东西。

*相比之下使用privateinternal其中那些预设至少增加了一个无论是在分别的一类或命名空间上下文信息(分别是什么使这些默认值,]),所以它是一个小东西更少让读者去思考。所以我更喜欢这是明确的。

相关问题