web-dev-qa-db-ja.com

ジェネリックプロパティの作成

シリアル化された値と型を格納するクラスがあります。既にキャストされた値を返すプロパティ/メソッドが必要です:

public String Value { get; set; }

public Type TheType { get; set; }

public typeof(TheType) CastedValue { get { return Convert.ChangeType(Value, typeof(_Type)); }

これはC#で可能ですか?

65
fer

プロパティを含むクラスがジェネリックであり、ジェネリックパラメーターを使用してプロパティを宣言する場合は可能です。

class Foo<TValue> {
    public string Value { get; set; }
    public TValue TypedValue {
        get {
            return (TValue)Convert.ChangeType(Value, typeof(TValue));
        }
    }
}

別の方法は、代わりに汎用メソッドを使用することです。

class Foo {
    public string Value { get; set; }
    public Type TheType { get; set; }

    public T CastValue<T>() {
         return (T)Convert.ChangeType(Value, typeof(T));
    }
}

System.ComponentModel.TypeConverterクラスを使用して変換することもできます。これは、クラスが独自のコンバーターを定義できるようにするためです。

編集:ジェネリックメソッドを呼び出すときは、ジェネリック型パラメーターを指定する必要があることに注意してください。

Foo foo = new Foo();
foo.Value = "100";
foo.Type = typeof(int);

int c = foo.CastValue<int>();

コンパイル時に型を知る必要があります。コンパイル時に型がわからない場合は、objectに格納する必要があります。その場合、次のプロパティをFooクラスに追加できます。

public object ConvertedValue {
    get {
        return Convert.ChangeType(Value, Type);
    }
}
101
Brannon

プロパティ、イベント、コンストラクターなどをジェネリックにすることはできません。メソッドと型のみをジェネリックにすることができます。ほとんどの場合、それは問題ではありませんが、時には痛みであることに同意します。 Brannonの答えは、2つの合理的な回避策を提供します。

54
Jon Skeet

ここに挙げた例が可能だとは思わない。 CastedValueのタイプはコンパイル時に定義する必要があります。つまり、ランタイム値(TheTypeプロパティの値)に依存することはできません。

編集:Brannonのソリューションには、プロパティではなくジェネリック関数を使用してこれを処理する方法に関するいくつかの良いアイデアがあります。

3
Charlie