1568

constreadonlyC#の違いは何ですか?

いつどちらを使用しますか?

4

31 に答える 31

1461

の明らかな違いは別として、

  • constVS値の定義時に値を宣言するreadonly必要がありますが、動的に計算できますが、コンストラクターが終了する前に割り当てる必要があります..その後、凍結されます。
  • constは暗黙的にstatic. それらにアクセスするには、ClassName.ConstantName表記法を使用します。

微妙な違いがあります。で定義されたクラスを考えてみましょうAssemblyA

public class Const_V_Readonly
{
  public const int I_CONST_VALUE = 2;
  public readonly int I_RO_VALUE;
  public Const_V_Readonly()
  {
     I_RO_VALUE = 3;
  }
}

AssemblyBAssemblyAコードでこれらの値を参照して使用します。これをコンパイルすると:

  • 値の場合はconst、検索置換のようなものです。AssemblyB値 2 はの ILに「焼き付けられます」 。これは、明日I_CONST_VALUE20 に更新した場合、AssemblyB再コンパイルするまで 2 のままであることを意味します。
  • readonly値の場合はref、メモリ ロケーションへのようなものです。AssemblyB値はの ILに焼き付けられません。これは、メモリ位置が更新された場合、AssemblyB再コンパイルせずに新しい値を取得することを意味します。したがって、I_RO_VALUEが 30 に更新された場合は、ビルドするだけで済みAssemblyA、すべてのクライアントを再コンパイルする必要はありません。

したがって、定数の値が変わらないことが確実な場合は、 a を使用しconstます。

public const int CM_IN_A_METER = 100;

ただし、変更される可能性のある定数がある場合 (egwrt 精度).. または疑わしい場合は、readonly.

public readonly float PI = 3.14;

更新: Aku はこれを最初に指摘したため、言及を得る必要があります。また、これを学んだ場所をプラグインする必要があります:効果的な C# - Bill Wagner

于 2008-09-11T08:24:41.770 に答える
309

const には落とし穴があります。別のアセンブリから定数を参照すると、その値は呼び出し元のアセンブリに直接コンパイルされます。そうすれば、参照先のアセンブリで定数を更新しても、呼び出し元のアセンブリでは変更されません!

于 2008-09-11T08:15:15.630 に答える
178

定数

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

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

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

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

  • コード実行がクラス参照にヒットしたとき (新しいインスタンスが作成されたとき、または静的メソッドが実行されたとき) に評価されます。
  • 静的コンストラクターが完了するまでに評価された値が必要です
  • これらに ThreadStaticAttribute を配置することはお勧めしません (静的コンストラクターは 1 つのスレッドでのみ実行され、そのスレッドの値を設定します。他のすべてのスレッドでは、この値は初期化されません)。
于 2008-12-02T11:50:14.753 に答える
68

追加する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
  }
}
于 2008-09-11T10:37:04.913 に答える
47

これはそれを説明します。要約: const は宣言時に初期化する必要があり、readonly はコンストラクターで初期化できます (したがって、使用するコンストラクターに応じて異なる値を持ちます)。

編集:微妙な違いについては、上記のギシュの落とし穴を参照してください

于 2008-09-11T08:04:07.870 に答える
44

const: どこでも変更できません。

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

于 2011-05-21T13:21:27.683 に答える
36

定数メンバーはコンパイル時に定義され、実行時に変更できません。定数は、キーワードを使用してフィールドとして宣言され、宣言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;
     }
}

定数

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

読み取り専用

  • それらはインスタンスレベルまたは静的のいずれかです
  • 値は実行時に評価されます
  • readonly は、宣言またはコンストラクターのコードで初期化できます
于 2012-09-17T11:48:03.097 に答える
33

読み取り専用には小さな落とし穴があります。readonly フィールドは、コンストラクター内で複数回設定できます。チェーンされた 2 つの異なるコンストラクターで値が設定されている場合でも、値は許可されます。

public class Sample {
    private readonly string ro;

    public Sample() {
        ro = "set";
    }

    public Sample(string value) : this() {
        ro = value; // this works even though it was set in the no-arg ctor
    }
}
于 2008-10-19T22:14:57.473 に答える
29

const はコンパイル時の定数ですが、 readonly では実行時に値を計算し、コンストラクターまたはフィールド初期化子に設定できます。したがって、「const」は常に一定ですが、「readonly」は割り当てられると読み取り専用になります。

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

于 2008-09-11T08:07:46.910 に答える
16

const がバージョンセーフではない、または参照型に関連していないことを示す別のリンクを次に示します。

まとめ

  • const プロパティの値はコンパイル時に設定され、実行時に変更できません
  • const は static としてマークできません。読み取り専用フィールドとは異なり、キーワードは static であることを示します。
  • const は、値 (プリミティブ) 型以外にすることはできません
  • readonly キーワードは、フィールドを変更不可としてマークします。ただし、プロパティはクラスのコンストラクター内で変更できます
  • readonly only キーワードを static と組み合わせて、(少なくとも表面的には) const と同じように動作させることもできます。2つの間のILを見ると、顕著な違いがあります
  • const フィールドは IL で「リテラル」としてマークされていますが、読み取り専用は「initonly」です。
于 2009-01-31T11:42:05.920 に答える
16

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

定数: デフォルトでは静的です。値はどこからでも変更できません (Ctor、関数、ランタイムなどどこにもありません)

于 2016-01-12T17:42:57.993 に答える
12

さらに別の落とし穴: 読み取り専用の値は、リフレクションを介して「不正な」コードによって変更される可能性があります。

var fi = this.GetType()
             .BaseType
             .GetField("_someField", 
                       BindingFlags.Instance | BindingFlags.NonPublic);
fi.SetValue(this, 1);

リフレクションを使用して、C# でプライベート読み取り専用継承フィールドを変更できますか?

于 2009-10-13T02:26:55.403 に答える
10

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

于 2008-09-11T08:03:46.157 に答える
7

これらは両方とも一定ですが、コンパイル時にも定数を使用できます。つまり、違いの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; }
  }
}
于 2008-09-17T13:02:06.403 に答える
6

私たちのオフィスのチーム メンバーの 1 人が、const、static、および readonly をいつ使用するかについて、次のガイダンスを提供しました。

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

最後に、const フィールドは static ですが、その逆は当てはまりません。

于 2008-10-02T20:43:37.180 に答える
5

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

const はデフォルトで静的であり、後で変更できない定数値で初期化する必要があります。コンストラクターでも値の変更は許可されていません。すべてのデータ型で使用できるわけではありません。ex-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;
    }
}

次に、次のように、読み取り専用フィールドを特定の値で初期化できます。

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

ここで、インスタンス objOne の readonly フィールドの値は 5 になり、objTwo の値は 10 になります。これは、const を使用して行うことはできません。

于 2014-12-15T13:01:10.900 に答える
5

const とマークされた変数は、厳密に型指定された #define マクロに過ぎず、コンパイル時に const 変数参照はインライン リテラル値に置き換えられます。結果として、特定の組み込みプリミティブ値型のみがこの方法で使用できます。読み取り専用とマークされた変数は、実行時にコンストラクターで設定でき、実行時にも読み取り専用が適用されます。これに関連して若干のパフォーマンス コストが発生しますが、それは、任意の型 (参照型を含む) で readonly を使用できることを意味します。

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

于 2008-09-11T08:41:51.527 に答える
3

別の落とし穴

const は実際には基本的なデータ型でのみ機能するため、クラスを操作する場合は、ReadOnly を使用する必要があると感じるかもしれません。ただし、罠に注意!ReadOnly は、オブジェクトを別のオブジェクトに置き換えることができないことを意味します (別のオブジェクトを参照させることはできません)。ただし、オブジェクトへの参照を持つプロセスは、オブジェクトの値を自由に変更できます。

そのため、ReadOnly はユーザーが変更できないことを意味すると誤解しないでください。C# には、クラスのインスタンス化で内部値が変更されるのを防ぐ単純な構文はありません (私の知る限り)。

于 2008-09-17T13:28:01.177 に答える
3

Aconstハードコーディングする必要があり、asはクラスのコンストラクターで設定readonlyできます。

于 2011-02-20T12:29:26.910 に答える
2

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

覚えておいてください: 参照型の場合、どちらの場合も (静的とインスタンス)、readonly 修飾子は、フィールドへの新しい参照の割り当てを防止するだけです。特に、参照が指すオブジェクトを不変にするわけではありません。

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

于 2014-04-05T14:39:18.013 に答える
2

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

于 2014-01-24T07:34:17.300 に答える
2

定数はリテラル値としてコンシューマーにコンパイルされますが、静的文字列は定義された値への参照として機能します。

演習として、外部ライブラリを作成してコンソール アプリケーションで使用し、ライブラリの値を変更して再コンパイルし (コンシューマ プログラムを再コンパイルせずに)、DLL をディレクトリにドロップして EXE を手動で実行します。定数文字列が変更されないこと。

于 2009-09-08T12:20:05.193 に答える
2

const と readonly は似ていますが、まったく同じではありません。const フィールドはコンパイル時の定数です。つまり、その値はコンパイル時に計算できます。読み取り専用フィールドを使用すると、型の構築中に一部のコードを実行する必要がある追加のシナリオが可能になります。構築後、読み取り専用フィールドは変更できません。

たとえば、const メンバーを使用して、次のようなメンバーを定義できます。

struct Test
{
    public const double Pi = 3.14;
    public const int Zero = 0;
}

3.14 や 0 などの値はコンパイル時の定数であるためです。ただし、タイプを定義し、そのプレハブ インスタンスを提供したい場合を考えてみましょう。たとえば、Color クラスを定義して、黒、白などの一般的な色の「定数」を提供したい場合があります。右辺はコンパイル時の定数ではないため、const メンバーでこれを行うことはできません。通常の静的メンバーでこれを行うことができます。

public class Color
{
    public static Color Black = new Color(0, 0, 0);
    public static Color White = new Color(255, 255, 255);
    public static Color Red = new Color(255, 0, 0);
    public static Color Green = new Color(0, 255, 0);
    public static Color Blue = new Color(0, 0, 255);
    private byte red, green, blue;

    public Color(byte r, byte g, byte b) {
        red = r;
        green = g;
        blue = b;
    }
}

しかし、おそらく黒と白の値を交換することによって、色のクライアントがそれをいじるのを防ぐものは何もありません. 言うまでもなく、これは Color クラスの他のクライアントを驚かせます。「読み取り専用」機能は、このシナリオに対処します。宣言に readonly キーワードを導入するだけで、柔軟な初期化を維持しながら、クライアント コードのいじくり回しを防ぎます。

public class Color
{
    public static readonly Color Black = new Color(0, 0, 0);
    public static readonly Color White = new Color(255, 255, 255);
    public static readonly Color Red = new Color(255, 0, 0);
    public static readonly Color Green = new Color(0, 255, 0);
    public static readonly Color Blue = new Color(0, 0, 255);
    private byte red, green, blue;

    public Color(byte r, byte g, byte b) {
        red = r;
        green = g;
        blue = b;
    }
}

const メンバーは常に静的であることに注意するのは興味深いことですが、readonly メンバーは、通常のフィールドと同様に、静的であってもなくてもかまいません。

これら 2 つの目的で 1 つのキーワードを使用することは可能ですが、これはバージョン管理の問題またはパフォーマンスの問題につながります。この (const) に 1 つのキーワードを使用し、開発者が次のように記述したと仮定します。

public class A
{
    public static const C = 0;
}

別の開発者が A に依存するコードを作成しました。

public class B
{
    static void Main() {
        Console.WriteLine(A.C);
    }
}

さて、生成されたコードは、AC がコンパイル時の定数であるという事実に依存できますか? つまり、AC の使用を単純に値 0 に置き換えることはできますか? これに「はい」と言った場合、それは A の開発者が AC の初期化方法を変更できないことを意味します。つまり、A の開発者は許可なく手を縛られます。この質問に「いいえ」と答えた場合、重要な最適化が見逃されています。おそらく、A の作成者は、AC が常にゼロになることを確信しています。const と readonly の両方を使用すると、A の開発者は意図を指定できます。これにより、バージョン管理の動作が向上し、パフォーマンスも向上します。

于 2013-09-28T08:19:52.010 に答える
1

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

于 2009-09-08T12:24:24.163 に答える
0

主な違いは、Const が #DEFINE に相当する C であることです。数は文字通りプリコンパイラのように置き換えられます。readonly は実際には変数として扱われます。

この区別は、プロジェクト A がプロジェクト B のパブリック定数に依存している場合に特に関係します。パブリック定数が変更されたとします。const/readonly の選択は、プロジェクト A の動作に影響します。

Const: プロジェクト A は、置換された定数でコンパイルされているため、新しい値をキャッチしません (もちろん、新しい const で再コンパイルされない限り)。

ReadOnly: プロジェクト A は常にプロジェクト B にその変数値を要求するため、B のパブリック定数の新しい値を取得します。

正直なところ、真に普遍的な定数 (Pi、Inches_To_Centimeters など) を除いて、ほぼすべてに対して readonly を使用することをお勧めします。変更される可能性のあるものについては、readonly を使用します。

これが役に立てば幸いです、アラン。

于 2008-09-15T21:30:19.740 に答える
0

上の人が言ったことに加えて一つ。読み取り専用の値 (例: readonly MaxFooCount = 4; ) を含むアセンブリがある場合、別の値 (例: readonly MaxFooCount = 5;) を持つそのアセンブリの新しいバージョンを出荷することで、呼び出し元のアセンブリが参照する値を変更できます。

ただし、const を使用すると、呼び出し元がコンパイルされるときに、呼び出し元のコードに組み込まれます。

このレベルの C# 習熟度に達している場合は、Bill Wagner の著書『Effective C#: 50 Specific Ways to Improvement Your C#』 (およびその他の 49 項目) を読む準備ができています。

于 2008-09-15T10:14:17.103 に答える