C#のprivate const変数とprivate readonly変数に違いはありますか?

StackOverflow https://stackoverflow.com/questions/410723

  •  03-07-2019
  •  | 
  •  

質問

C#で private const 変数または private static readonly 変数を持つことには違いがあります( const コンパイル時の式)?

どちらもプライベートであるため、他のライブラリとのリンクはありません。それで何か違いが出るでしょうか?たとえば、パフォーマンスの違いを生むことができますか?インターンストリング?同様の何か?

役に立ちましたか?

解決

まあ、属性にはコンパイル時として存在するconstを使用できます。 .cctor は設定などから初期化できるため、静的な読み取り専用変数の値を予測することはできません。

使用に関しては、定数は呼び出しコードに焼き付けられます。つまり、 library dllを再コンパイルして public 定数を変更しても、コンシューマを変更しない場合、コンシューマは元の値を使用します。読み取り専用変数では、これは起こりません。これを反転すると、定数は(非常にわずかに)高速になります。これは、値を参照する必要がなく、単に値を読み込むからです。

再インターン;これは手動で行うことができますが、これは最も一般的にはリテラルのコンパイラ/ランタイム機能です。リテラルを介して読み取り専用フィールドを初期化する場合:

someField = "abc";

その後、" abc" がインターンされます。 configから読み込んだ場合、読み込まれません。定数文字列はリテラルである必要があるため、インターンも行われますが、アクセス方法が異なります。フィールドからの読み取りは、 ldstr

他のヒント

実際、2つのタイプは初期化後に変更することはできませんが、いくつかの違いがあります:

  • 「const」は宣言時に初期化する必要があります(コンパイル時に)が、「readonly」は宣言時またはコンストラクター内(arランタイム)で初期化できます。

たとえば、この状況ではconstを使用できます。

public class MathValues
{
  public const double PI = 3.14159;
}

この場合、読み取り専用の方が優れています:

public class Person
{
    public readonly DateTime birthDate;

    public Person(DateTime birthDate)
    {
        this.birthDate = birthDate;
    }
}

または

public class Person
{
    public readonly DateTime birthDate = new DateTime(1986, 1, 24);
}
  • 'const'は静的であるため、そのクラスのすべてのインスタンス間で共有され、直接アクセスできます(MathValues.PIなど)が、 'readonly'は静的ではありません。結果として、constは静的であるため 'static const'のような宣言は違法ですが、 'static readonly'は有効です

  • 'const'は、整数型(sbyte、byte、short、ushort、int、uint、long、ulong、char、float、double、decimal、bool、またはstring)、列挙、またはnullへの参照(実行時に「new」キーワードで初期化されるため、クラスまたは構造体ではありません) p>

定数について注意すべき点は、実際に実行可能ファイルに保存されることです。そのため、定数の多くを宣言すると、実行可能ファイルのサイズが大きくなります。

通常、これは大きな問題ではありませんが、私の友人は、「すべてがconstでなければならない」ことを強制する会社で働いていました。コンパイルされた実行可能ファイルのサイズを大幅に増やすことに成功しました。

C#.NET const readonly 、および static readonly フィールドの違いは次のとおりです(この記事)。

>

定数

  • デフォルトでは静的
  • コンパイル時の値が必要です(つまり、" A" +" B"は使用できますが、メソッド呼び出しは使用できません)
  • 属性で使用できます
  • それらを使用するすべてのアセンブリにコピーされます(すべてのアセンブリは値のローカルコピーを取得します)
  • 関数内で宣言できます

読み取り専用インスタンスフィールド

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

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

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

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

constはデフォルトで静的であり、定数値で初期化する必要がありますが、後で変更することはできません。コンストラクターでも値の変更は許可されていません。すべてのデータ型で使用できるわけではありません。 元の日時の場合。 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は静的として宣言できますが、必須ではありません。宣言時に初期化する必要はありません。その値は、コンストラクターを使用して割り当てまたは変更できます。したがって、インスタンスクラスメンバとして使用すると利点が得られます。 2つの異なるインスタンス化では、読み取り専用フィールドの値が異なる場合があります。 例:-

class A
{
    public readonly int Id;

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

読み取り専用フィールドは、次のようにインスタント固有の値で初期化できます。

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

ここでは、インスタンスobjOneの読み取り専用フィールドの値は5で、objTwoの値は10です。これはconstを使用してはできません。

使用中ですか?あんまり。定数はコンパイル時に評価されますが、読み取り専用は実行時に評価されます。コンストラクターで読み取り専用変数に値を割り当てることもできます。

もう1つ。私はそれを見逃したかもしれませんが、私は上記のコメントでこれを見ませんでした。定数配列を作成することはできません。

private const int[] values = new int[] { 1, 2, 3 };

ただし、静的な読み取り専用フィールドを使用して作成できます

private static readonly int[] values = new int[] { 1, 2, 3 };

したがって、許容値のリストなどの配列定数が必要で、列挙が適切でない場合は、静的読み取り専用が唯一の方法です。たとえば、配列が次のようなNULL可能整数の場合:

private static readonly int?[] values = new int?[] { null, 1, 2, 3 };

定数でそれを行うことはできません、できますか?

違いは、静的読み取り専用フィールドの値は実行時に設定されるため、包含クラスによって変更できるのに対して、constフィールドの値はコンパイル時定数に設定されることです。

静的な読み取り専用の場合、包含クラスはそれのみを変更できます

変数宣言内(変数初期化子を使用) 静的コンストラクター(インスタンスコンストラクター、静的でない場合) 通常、静的読み取り専用は、フィールドの型がconst宣言で許可されていない場合、またはコンパイル時に値が不明な場合に使用されます。

インスタンスの読み取り専用フィールドも許可されています。

参照型の場合、両方の場合(静的およびインスタンス)で、読み取り専用修飾子はフィールドへの新しい参照の割り当てのみを禁止することに注意してください。具体的には、参照によってポイントされるオブジェクトを不変にしません。

class Program

{

  public static readonly Test test = new Test();

  static void Main(string[] args)

  {

     test.Name = "Program";

     test = new Test(); // Error: A static readonly field cannot be assigned to (except in a static constructor or a variable initializer)

  }

}

class Test

{

   public string Name;

}

違いは、静的読み取り専用は包含クラスによって変更できますが、constは変更できず、コンパイル時定数に初期化する必要があることです。静的な読み取り専用のケースを少し拡張するために、包含クラスはそれを変更することしかできません:

-変数宣言内(変数初期化子を使用)。

-静的コンストラクター(静的でない場合はインスタンスコンストラクター)。


C#.NETのconstキーワード

例: public const string abc =“ xyz&#8221 ;; 宣言時にのみ初期化されます。 値はコンパイル時に評価され、実行時に変更することはできません。 変更しようとすると、コンパイルエラーが発生します。 Constはすでに静的なものです。 クラスと構造体は実行時に新しいキーワードで初期化されるため、クラスまたは構造体に定数を設定することはできません。しかし、それは整数型でなければなりません。 C#.NETの読み取り専用キーワード

例:読み取り専用のパブリック文字列abc; 宣言コードまたはコンストラクタコードで初期化できます。 値は実行時に評価されます。 静的またはインスタンスレベルの属性として宣言できます。 読み取り専用フィールドは、実行時に新しいキーワードを使用することにより、複雑なオブジェクトを保持できます。

読み取り専用フィールドは、クラスの宣言またはコンストラクタで初期化できます。したがって、読み取り専用フィールドは、使用されるコンストラクターに応じて異なる値を持つことができます

読み取り専用メンバーは、次の例のようにランタイム定数に使用することもできます。

public static readonly uint currentTicks = (uint)DateTime.Now.Ticks;

読み取り専用フィールドは暗黙的に静的ではないため、必要に応じて静的キーワードを明示的に読み取り専用フィールドに適用する必要があります。これは、暗黙的に静的なconstフィールドには許可されていません。

読み取り専用メンバーは、初期化時に新しいキーワードを使用して、複雑なオブジェクトを保持できます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top