5

の C# 仕様によると10.4 Constants:

定数宣言で指定する型は、 sbyte、byte、short、ushort、int、uint、long、ulong、char、float、double、decimal、bool、string、enum-type、または reference-type でなければなりません。各定数式は、ターゲット型の値、または暗黙的な変換によってターゲット型に変換できる型の値を生成する必要があります (§6.1)。

なぜ私は次のことができないのですか:

public class GenericClass<T>
    where T : class
{
    public const T val = null;
}

次の理由により、それが可能になるはずです。

  • where T : classつまり、The type argument must be a reference type; this applies also to any class, interface, delegate, or array typeMSDNから)
  • is以外の参照型の定数に可能な唯一のstringnullです

可能な説明はありますか?

4

2 に答える 2

0

Eric Lippertは、これはバグであり、許可されるべきであると認めました。

バグを見つけたようです。バグが仕様にあり、型パラメーターが有効な型ではないことを明示的に指摘する必要があるか、バグがコンパイラにあり、それを許可する必要があります。

于 2013-08-20T05:22:24.617 に答える
0

考えられる説明

CLRstaticがジェネリック クラスのメンバーを初期化する方法、またはジェネリック型で静的コンストラクターを呼び出すタイミングを検討してください。通常、プログラムが最初にロードされるときに静的初期化が行われます。ただし、ジェネリック クラスは、そのクラスのインスタンスが最初に作成されるときに静的メンバーを初期化します。

ジェネリック クラスは単一の型ではないことに注意してください。T型宣言で渡されるすべてのシングルが新しい型を作成しています。

次に、constコンパイル時に評価する必要がある式を考えてみましょう。T はクラスとして制約されているため、値 null を受け取ることができますがval、実行時にクラスが作成されるまで変数はメモリに存在しません。

たとえば、const T valが有効かどうかを考えてみましょう。次に、コードの他の場所で使用できます。

GenericClass<string>.val
GenericClass<object>.val

編集

どちらの式も値を持ちますnullが、前者は型string、後者は型objectです。コンパイラが置換を実行するには、問題の定数の型定義を知る必要があります。

制約はコンパイル時に適用される場合がありますが、オープン ジェネリックは実行時までクローズ ジェネリックに変換されません。したがって、GenericClass<object>.valコンパイラのローカル メモリに格納して置換を実行することはできません。これは、コンパイラがジェネリック クラスのクローズド フォームをインスタンス化せず、定数式をインスタンス化する型がわからないためです。

于 2013-07-24T04:37:58.113 に答える