web-dev-qa-db-ja.com

構造体をconstとして宣言できないのはなぜですか?

38
Lazlo

値型コンストラクターはanything-たとえば、時刻に基づいてロジックを切り替える可能性があるためです。定数値型は知的に理にかなっていますが、コンストラクターが自由に実行できる柔軟性があるため、実際にはカスタム値型を処理できません。 (定数はcompile time、で評価されることに注意してください。つまり、コンストラクターはコンパイル時に実行する必要があります。)

44
cdhowie

C#のconstは、それが決定できることを意味しますコンパイル時。これが、intstringなどのプリミティブ型のみがconstになることができる理由です。

C出身の場合は、readonlyキーワードの方が適している可能性があります。

22
vcsjones

C#コンパイラが構造体型のconst値を生成するには、そのすべてのフィールドにどの値を入れるかを知っている必要があります。 C#コンパイラは、Decimalのような特定の型のフィールドを初期化する方法を本質的に知っていますが、ほとんどの値型ではそのような知識はありません。

すべてのstructフィールドが公開されているコンテキストで、コンパイラーが構造体型の定数値を宣言する手段を提供することは可能です。構造体のフィールドがprivateの場合、その型の定数は構造体内でのみ宣言できます。フィールドがinternalの場合、定数はアセンブリ内の任意の場所で宣言できます。 publicであれば、どこでも宣言できます。

私はそのような機能を見たいのですが、主流の.net言語がそれを実装することを期待していません。コンパイラが本質的に知っている型の名前付き定数は、他の定数式に参加できますが、static readonly変数は参加できません。 NumRowsが4に等しい定数の場合、NumRowsが外部アセンブリで定義されていても、Arr[3*NumRows+7]のような式はArr[19]で置き換えることができます。これにより、そのような定数はstatic readonly変数よりも大幅に有利になります。ただし、定数がコンパイラーが本質的に認識しない型である場合、定数式に参加する能力は非常に制限され、そもそも定数であることの利点が事実上打ち消されます。値型定数に公開フィールドがある場合、コンパイラーがそのフィールドの値を定数として使用することは可能ですが、.net言語の作成者は公開フィールドを持つ構造に哲学的に反対しているため、私は期待していません。それらが可能であっても、そのような使用を許可します。

static readonly変数よりも定数を優先する使用例がいくつかありますが、そのようなケースの多くは、既存のタイプを使用して許容できる範囲で処理できます。たとえば、ライブラリはconst Int64を公開してそのバージョンに関する情報をエンコードし、その値をGetLinkedVersionInfoメソッドのデフォルトパラメータ値として使用する場合があります。問題の値は、コンパイル時に呼び出しコードに「組み込まれる」ため、メソッドは呼び出し元がリンクされているライブラリのバージョンを報告し、実行しているバージョンに互換性の問題があるかどうかを識別できます。

4
supercat

単純な可変構造体でreadonlyキーワードをテストしました。

_struct Test
{
   public int value;

   public void setInt(int val)
   {
      value = val;
   }
}

static class Program
{
   public static readonly Test t = new Test();

   static void Main()
   {
      Console.WriteLine(t.value); // Outputs "0"
      t.setInt(10);
      //t.value = 10;  //Illegal, will not let you assign field of a static struct
      Console.WriteLine(t.value); // Still outputs "0"
   }
}
_

readonly構造体は技術的にはコンパイル時定数ではありませんが、ランタイムはそれを変更させません。ステップ実行でもsetInt()メソッドをスローしましたが、値の変更のように見えますが、Mainの変更は表示されません。

構造体自体は「読み取り専用」メモリに配置され、変更できないようになっていると思います。ポインターを一定に保つクラスとは異なり、クラスフィールド自体を自由に変更できます。

つまり、可変構造体であっても、_static readonly_は事実上constであるように見えます。

3
Cemafor