2017-08-25 3 views
-1

私は最近、デフォルト値で初期化する場合、クラス変数(値はhttps://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/default-values-table)を初期化すべきではないと述べた人が出てきました。 それは私にとって非常に間違って聞こえる。これで実際にパフォーマンスが向上していますか? 以下の例では、フラグを最初にfalseに設定することは望ましくありません(シナリオではfalseと仮定します)。クラス変数を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はそのページを、アサーションのソースではなく、デフォルト値である_what_への参照として使用していたと思います。つまり、「私の友人は、変数を初期値(ここでは[https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/default-values-表)。" –

答えて

0

C#では未定義の変数を使用できません。 CLRは依然としてデフォルトに初期化されます。可能であれば変数を設定しないと、後でこのアサーションがコンパイラによってチェックされます。

OTOHのフィールドには、このようなチェックはありません。デフォルト値をデフォルト値に設定すると、これらのフィールドをすべてデフォルト値に設定してデバッガを実行することになります。それらを設定しないと、QoL改善wrtデバッグエクスペリエンスが得られます

+1

'C#は未定義変数の使用を許可していません.'それは真実ではありません。 *特定の*変数は初期化する必要があります(つまり、ローカル)。すべてではありません。 – Servy

+0

地方自治体が未定義であることが許されない理由についての良い答えがありますが、クラス変数は次のとおりです。https://stackoverflow.com/a/30820127/2193107これは、何かが実際に割り当てられていないかどうかを検出する複雑さと主に関係しています。 – JBC

0

あなたがカバーの下にある値オブジェクトであるboolフィールドを参照していて、nullにはならないことがわかっている場合。デフォルトでは「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に設定されますどんな違いがあっても)、DefaultInitNoInitの間には、それが何であるかに違いはありません〜にmpiled。 C#に逆コンパイルする場合は、明示的にfalseに設定するか、最初の場所に書き込むかのように、独自の呼び出しを行う必要があります。

結果の点では、2つはまったく同じです。

これでは、違いは完全に重要ではありません。 (むしろ、私がやっていたプロジェクトは、一貫して私が気に入らないアプローチを使用していたと思っていましたが、それは非常に矛盾していました。

しかし、多くの初期化はちょっと忙しいかもしれませんし、何らかの型のデフォルトが何であるかを知るのに十分な情報を*追加しないで、特定の値に初期化するときに明確にします。

とにかくコンストラクタの値を設定しようとしている(または時には行く)場合は、特に冗長に思えるかもしれません。 (ただし、デフォルトに初期化すると、コンストラクタの設定は、コンストラクタで設定するだけでなく、デフォルト以外のものに初期化する場合は同じではありません。必ずしもそうではない、特に初期化に副作用がある場合)。

また、デバッグセッション中に信号対雑音比が低下して、面白い初期化が多く発生する可能性があります。

コーディング規約を作成するのは合理的なことだと思いますが、私はそれらの慣習がどのようなものかについてあなたが言及している人に同意しますが、パフォーマンスに影響を与えるものではありません。これらは、デフォルトでは、少なくとも(]は、それぞれ、それらのデフォルトを作るものです)1は、それぞれのクラスまたは名前空間コンテキストにあるかどうかの情報を追加しているので、それは一つの小さなことだところprivateまたはinternalを使用して対照的に

*読者が考えることが少ない。だから私はそれが明白であることを好みます。

関連する問題