c# - グループ - static read




constとreadonlyの違いは何ですか? (20)

CONST

  1. constキーワードは、フィールドやローカル変数に適用できます。
  2. 宣言時にconstフィールドを割り当てる必要があります
  3. メモリが割り当てられていないコンパイル後にconst値がILコード自体に埋め込まれるためです。 それはconst変数のすべての出現を見つけ、その値で置き換えるようなものです。 したがって、コンパイル後のILコードは、const変数の代わりにハードコードされた値を持ちます
  4. C#のConstは、デフォルトでは静的です。
  5. 値はすべてのオブジェクトで一定です
  6. dllバージョン管理の問題があります - これは、public const変数またはプロパティを変更するたびに(実際には理論的に変更されていないと思われます)、この変数を使用する他のdllまたはアセンブリを再構築する必要があることを意味します
  7. C#組み込み型のみ定数として宣言できます
  8. Constフィールドはrefまたはoutパラメータとして渡すことはできません

ReadOnly

  1. readonlyキーワードはローカル変数ではないフィールドにのみ適用されます
  2. 他の方法ではなく、宣言時またはコンストラクタ時にreadonlyフィールドを割り当てることができます。
  3. readonlyフィールドに割り当てられた動的メモリで、実行時に値を取得できます。
  4. Readonlyは、作成されたオブジェクトに属し、クラスのインスタンスのみでアクセスされます。 クラスメンバにするには、readonlyの前にstaticキーワードを追加する必要があります。
  5. 値は、使用されるコンストラクタ(クラスのオブジェクトに属する)によって異なる場合があります。
  6. 非プリミティブ型(参照型)を読み込み専用として宣言した場合、参照は不変であり、その中に含まれるオブジェクトではありません。
  7. 値は実行時に取得されるため、読み取り専用のフィールドやプロパティではdllのバージョン管理に問題はありません。
  8. readonlyフィールドは、コンストラクタコンテキストでrefまたはoutパラメータとして渡すことができます。

constreadonly違いは何ですか?もう一方を使っていますか?


定数

  • 定数はデフォルトで静的です
  • コンパイル時に値を持たなければなりません(例えば、3.14 * 2の値を持ちますが、メソッドを呼び出すことはできません)
  • 関数内で宣言できます
  • それらを使用するすべてのアセンブリにコピーされます(すべてのアセンブリは値のローカルコピーを取得します)
  • 属性で使用できる

Readonlyインスタンスフィールド

  • コンストラクタが終了するまでに値を設定している必要があります。
  • インスタンスの作成時に評価される

静的読み取り専用フィールド

  • コード実行がクラス参照にヒットしたときに評価されます(新しいインスタンスが作成されたとき、または静的メソッドが実行されたとき)
  • 静的コンストラクタが完了するまでに評価された値を持つ必要があります
  • これらのインスタンスにThreadStaticAttributeを設定することはお勧めできません(スタティックコンストラクタはあるスレッドのみで実行され、そのスレッドの値が設定され、他のすべてのスレッドはこの値が初期化されません)

C#.Netのconstフィールドとreadonlyフィールドには大きな違いがあります

constはデフォルトでは静的であり、定数値で初期化する必要があります。後で変更することはできません。 値の変更はコンストラクタでも許可されていません。 すべてのデータ型で使用することはできません。 旧DateTimeの場合。 DateTimeデータ型では使用できません。

public const DateTime dt = DateTime.Today;  //throws compilation error
public const string Name = string.Empty;    //throws compilation error
public readonly string Name = string.Empty; //No error, legal

readonlyはstaticとして宣言できますが、必ずしも必要ではありません。 宣言時に初期化する必要はありません。 その値はコンストラクタを使用して割り当てまたは変更できます。 したがって、インスタンスクラスメンバとして使用すると利点があります。 2つの異なるインスタンス化は、読み取り専用フィールドの異なる値を有することができる。 例えば、

class A
{
    public readonly int Id;

    public A(int i)
    {
        Id = i;
    }
}

次に、readonlyフィールドは、次のように瞬時の特定の値で初期化できます。

A objOne = new A(5);
A objTwo = new A(10);

ここでは、インスタンスobjOneはreadonlyフィールドの値を5、objTwoは10を持ちます。これはconstを使用することはできません。


ReadOnly:値はクラスのコンストラクタから一度だけ初期化されます。
const:任意の関数で初期化できますが、一度だけです


constとマークされた変数は、コンパイル時const型の変数参照がインラインのリテラル値に置き換えられたときに、強く型付けされた#defineマクロよりも少しです。 結果として、特定のビルトインプリミティブ値型のみがこのように使用される。 readonlyとマークされた変数は、実行時にコンストラクタで設定することができ、実行時にその読み込み専用性が強制されます。 これに関連するマイナーなパフォーマンスコストがありますが、どのタイプ(偶数参照タイプ)でも読み取り専用を使用できることを意味します。

また、const変数は本質的に静的ですが、必要に応じてreadonly変数はインスタンス固有のものになることがあります。


constはコンパイル時定数ですが、readonlyでは、実行時に値を計算し、コンストラクタまたはフィールドイニシャライザで値を設定することができます。 したがって、 'const'は常に定数ですが、 'readonly'は割り当てられた後は読み取り専用です。

C#チームのEric Lippertは、さまざまな種類の不変性に関する詳細情報を提供しています


ここでは、constがバージョンセーフではないか、参照型に関連するかを示す別のリンクがあります。

要約

  • あなたのconstプロパティの値はコンパイル時に設定され、実行時に変更することはできません
  • Constは静的としてマークすることはできません。キーワードは、読み込み可能なフィールドとは異なり、静的であることを示します。
  • Constは値(プリミティブ)型以外は何もできません
  • readonlyキーワードは、フィールドを変更不可能とマークします。 ただし、プロパティはクラスのコンストラクタ内で変更できます
  • readonly onlyキーワードは、静的と組み合わせることで、constと同じように動作させることができます(atleast on surface)。 あなたが2人の間のILを見ると、顕著な違いがあります
  • constフィールドは、ILでは "literal"とマークされ、readonlyは "initonly"

const :どこでも変更することはできません。

readonly :この値はコンストラクタでのみ変更できreadonly 。 通常の機能では変更できません。


定数

constフィールドが定義されている場合は、値をconstフィールドに渡す必要があります。 次に、コンパイラは定数の値をアセンブリのメタデータに保存します。 つまり、boolean、char、byteなどのプリミティブ型に対してのみ定数を定義できます。 定数は常にインスタンスメンバーではなく静的メンバーとみなされます。

読み取り専用

読み取り専用フィールドは、実行時にのみ解決できます。 つまり、フィールドが宣言された型のコンストラクタを使用して値の値を定義できます。 検証は、コンストラクタ以外のメソッドによってフィールドが読み込まれないようにコンパイラによって行われます。

この記事で説明している両方の詳細


読み取り専用 :実行時にCtorによって値を変更できます。 しかし、メンバー関数ではありません

Constant :defult staticによって。 値はどこからでも変更することはできません(Ctor、関数、ランタイムなどno-where)


どちらも定数ですが、コンパイル時にもconstが使用できます。 つまり、相違点の1つは、const変数を属性コンストラクタへの入力として使用できますが、読み取り専用変数では使用できないということです。

例:

public static class Text {
  public const string ConstDescription = "This can be used.";
  public readonly static string ReadonlyDescription = "Cannot be used.";
}

public class Foo 
{
  [Description(Text.ConstDescription)]
  public int BarThatBuilds {
    { get; set; }
  }

  [Description(Text.ReadOnlyDescription)]
  public int BarThatDoesNotBuild {
    { get; set; }
  }
}

もうひとつ。

constは基本的なデータ型でしか動作しないので、クラスで作業したい場合は、ReadOnlyを "強制的に"使用すると感じるかもしれません。 しかし、トラップには注意してください! ReadOnlyは、オブジェクトを別のオブジェクトに置き換えることができないことを意味します(別のオブジェクトを参照することはできません)。 しかし、オブジェクトへの参照を持つプロセスは、オブジェクトの値を自由に変更することができます!

ReadOnlyがユーザーが物事を変えることができないことを意味すると考えることに混同しないでください。 C#には、クラスのインスタンス化が(私が知る限り)内部値を変更しないようにするための単純な構文はありません。


主に; 実行時に静的な読み取り専用フィールドに値を非定数値に割り当てることができますが、constには定数値を割り当てる必要があります。


人々が上に述べたことに加えて1つのこと。 読み取り専用値(たとえば、読み取り専用MaxFooCount = 4;)を含むアセンブリがある場合、アセンブリの新しいバージョンを異なる値で出荷することによって、呼び出しアセンブリが参照する値を変更できます(たとえば、読み取り専用MaxFooCount = 5;)

しかし、constでは、呼び出し元がコンパイルされたときに呼び出し元のコードに折り返されます。

このレベルのC#の習熟度に達していれば、あなたはBill Wagnerの本「効果的なC#:50の具体的なC#の改善方法」の準備が整いました。


定数メンバはコンパイル時に定義され、実行時に変更することはできません。 定数は、 constキーワードを使用してフィールドとして宣言され、宣言されたときに初期化する必要があります。

public class MyClass
{
    public const double PI1 = 3.14159;
}

readonlyメンバは、それが不変の値を表す点で定数のようなものです。 違いは、 readonlyメンバは、コンストラクタ内で実行時に初期化され、宣言されたときに初期化できる点です。

public class MyClass1
{
     public readonly double PI2 = 3.14159;

     //or

     public readonly double PI3;

     public MyClass2()
     {
         PI3 = 3.14159;
     }
}

const

  • staticと宣言することはできません(暗黙的に静的です)
  • 定数の値はコンパイル時に評価されます。
  • 定数は宣言時にのみ初期化されます

読み取り専用

  • インスタンスレベルまたは静的のいずれかになります。
  • 値は実行時に評価されます。
  • readonlyは、宣言やコンストラクタ内のコードで初期化することができます

定数変数は、コンパイル時に宣言され、初期化されます。 ワードの後に​​値を変更することはできません。 読み取り専用変数は、クラスの静的コンストラクタからのみ初期化されます。 読み取り専用は、実行時に値を割り当てる場合にのみ使用されます。


私たちのオフィスのチームメンバーの1人は、const、static、およびreadonlyをいつ使うべきかに関する以下のガイダンスを提供しました:

  • クラスのすべてのインスタンスまたはコンシューマが値を変更してはならない場所にアクセスできるようにする、実行時に知ることができる型の変数(文字列リテラル、int、double、列挙型など)がある場合は、 constを使用します。
  • クラスのすべてのインスタンスまたはコンシューマが値の変更可能な場所にアクセスできるようにするデータがある場合は、 staticを使用します
  • クラスのすべてのインスタンスまたはコンシューマが値を変更しない場所にアクセスできるようにするために、実行時に(オブジェクト)知ることのできない型の変数を持つ場合は、 静的な読み取り専用を使用します
  • オブジェクトの作成時に変更してはならないことが分かるインスタンスレベルの変数がある場合は、 readonlyを使用します

1つの最後の注意:constフィールドは静的ですが、逆は真ではありません。


私は、 const値はすべてのオブジェクトで同じである(とリテラル式で初期化する必要がありreadonly )、 readonlyは各インスタンスごとに異なる可能性があると信じています...


追加するだけで、参照型のためのReadOnlyは、その参照が値ではなく読み込み専用になります。 例えば:

public class Const_V_Readonly
{
  public const int I_CONST_VALUE = 2;
  public readonly char[] I_RO_VALUE = new Char[]{'a', 'b', 'c'};

  public UpdateReadonly()
  {
     I_RO_VALUE[0] = 'V'; //perfectly legal and will update the value
     I_RO_VALUE = new char[]{'V'}; //will cause compiler error
  }
}

違いは、静的なreadonlyフィールドの値は実行時に設定されるため、プログラムの実行ごとに異なる値を持つことができる点です。 ただし、constフィールドの値はコンパイル時定数に設定されます。

覚えておいてください:参照型の場合、両方の場合(静的とインスタンス)、readonly修飾子はフィールドへの新しい参照の割り当てを禁止します。 具体的には、参照によって指されたオブジェクトを不変にするものではありません。

詳細については、次のトピックに関するC#のよくある質問を参照してくださいhttp://blogs.msdn.com/csharpfaq/archive/2004/12/03/274791.aspx : http://blogs.msdn.com/csharpfaq/archive/2004/12/03/274791.aspx





readonly