2

C# のジェネリック クラスの利点は、型に制約を設定できるため、いくつかの制約を満たす型のみが受け入れられることです。例えば:

public class Foo<T> where T : Bar, IBaz, IFoobar {

    public Foo (T value) {
        //initialize
    }

}

これはT、記述された 3 つのクラスから派生した型とのみ統合できることを意味します。

メソッドを使用する場合、メソッドをジェネリックにすることもできます。しかし、コンストラクターでそのような制約を指定できないのはなぜだろうと思っていました。例えば:

public class Foo {

    public Foo (Bar & IBaz & IFoobar value) {
        //initialize (the "&" syntax is just an example)
    }

}

valueクラスをジェネリックにすることもできますが、コンストラクターだけが を使用し、クラスの他のメソッドが に依存しない場合、これはかなり面倒ですT。ジェネリック クラスでは解決が難しい問題もあります。たとえばSomeComparer<T,Q> : IComparer<Foo<T>,Foo<Q>>、実際にはまったくジェネリックではないジェネリック クラスの負荷を導入する比較子を作成する必要があります。

型システムは引数がすべての型制約を満たしているかどうかを簡単にチェックできるため、これが実装されていない理由がわかりません。

C# 言語仕様で結合型を定義しないという引数は何ですか?

4

2 に答える 2

1

この機能は便利かもしれませんが、実装されていません。C# チームには非常に多くの時間しかありません。これを難しくする要因はたくさんあります:FooFoo<T>クラスがあり、それぞれに非ジェネリックとFoo<U>コンストラクタがあるとします。を呼び出す場合new Foo<int>(1)、それはそれですか、Foo..ctor<U>それともFoo<T>..ctorですか? そして、Foo<T>..ctor<U>によって参照されていnew Foo<int><string>("")ますか?いくつかの新しい構文を導入せずに行うことはできず、それが行われているのを見ることができる方法を混乱させるため、コンストラクターでジェネリックを許可しないことが最善の方法です。

非ジェネリック クラスにジェネリック メソッドを記述することで回避できます。

void Main()
{
    Foo foo = Foo.GetInstance(new BarBazAndFoobarImplementer());
}
public sealed class Foo {
    private Foo(Bar value) {
        this.Thing1 = value.BarProperty;
        this.Thing2 = ((IBaz)value).IBazProperty;
        this.Thing3 = ((IFoobar)value).IFoobarProperty;
    }

    public static Foo GetInstance<T>(T value) where T : Bar, IBaz, IFoobar {
        return new Foo(value);
    }
}

Foo.GetInstance<U>(..)(明確に and を呼び出すことができるため、これは上記の問題に悩まされることはありませんFoo<T>.GetInstance<U>(..))

于 2013-10-30T15:00:37.477 に答える
1

このようなことを行う 1 つの方法は、プライベート コンストラクターとファクトリ メソッドを使用することです。

public class Foo 
{
    public static Foo Create<T>(T value) where T : Bar, IBaz, IFoobar
    {
        return new Foo(value);
    }

    private Foo(Bar value)
    {
        // whatever
        // feel free to cast to IBaz or IFoobar as needed
    }
}

コンストラクターはその型のインスタンスを構築することになっているため、コンストラクターではそれを行うことはできません。あなたは何をしますvalueか?おそらくフィールドに保存しますが、フィールドのタイプは何でしょうか?

より良い方法はBar、またはから派生したクラスがBar両方のインターフェースを実装することです。

于 2013-10-30T15:05:50.127 に答える