「何でも」(C#の)のジェネリックコレクションを返すメソッドを宣言する方法

StackOverflow https://stackoverflow.com/questions/1450713

質問

私はまた、抽象基本クラスから派生したエンティティの項目を格納する抽象基本クラスから派生するジェネリックコレクションクラスの階層を使用しています:

abstract class ItemBase { }

class MyItem : ItemBase
{
    public MyItem()
    {
    }
}


abstract class CollectionBase<T> : Collection<T> where T : ItemBase, new() { }

class MyCollection : CollectionBase<MyItem> { }

このモデルの目的は、 CollectionBaseから派生したクラスのメンバーに厳密な型の規律を強制するために、これらのメンバーは、既定のパブリックコンストラクタを持っていることを保証するためです。これまでのところそれが動作します。

今、私はCollectionBaseにから派生したクラスのインスタンスを返すファクトリメソッドを作成したいです。私はいつものアプローチが可能だろうと理解します:

public CollectionBase<T> CreateCollection<T>();

...または多分...

public T Create CreateCollection<T>();

しかし、問題は、呼び出し元のルーチンは、「T」が必要になるのか分からないということです。これは、コレクションの特定のタイプを返すように決定する必要がありますファクトリメソッドそのものです。だから私は、「戻り値の型は、 CollectionBaseから派生します」と言う非ジェネリックメソッドのシグネチャを必要としています。 (それは法的だったら)私はこのような何かを考える...

public CollectionBase<> CreateCollection();

私は、これは、それらの厄介な一般的な分散の問題の他であると仮定し、それでも対象にエリックリペットの広範な説明を読んだ後、私はまだ私は何をしようとしていますが、C#4.0で実現可能である可能性が高いかどうかは不明だ、とするかどうかがC#の3.0で簡単な回避策です。

あなたのアイデアを事前に感謝します。

役に立ちましたか?

解決

のは、ファクトリメソッドは、単一の項目を作成したとしましょう。あなたが持っているでしょう。

public ItemBase CreateItem();

あなたはより具体的な何かを知ることができないのでItemBaseを使用する必要があります。収集方法にその原則を適用すると、次のようになります。

public CollectionBase<ItemBase> CreateCollection();

により分散の不足のために、あなたはCollectionBase<ItemBase>から派生して作成された実際のコレクションをラップアダプタクラスを必要とします。

C#4.0では、あなただけの実際のコレクションを返します。

編集の工場は、組み込みアダプターで、次のようになります。

public class CollectionFactory
{
    public CollectionBase<ItemBase> CreateCollection()
    {
        if(someCondition)
        {
            return CreateAdapter(new MyCollection());
        }
        else
        {
            return CreateAdapter(new MyOtherCollection());
        }
    }

    private static CollectionAdapter<T> CreateAdapter<T>(CollectionBase<T> collection) where T : ItemBase, new()
    {
        return new CollectionAdapter<T>(collection);
    }

    private class CollectionAdapter<T> : CollectionBase<ItemBase> where T : ItemBase, new()
    {
        private CollectionBase<T> _collection;

        internal CollectionAdapter(CollectionBase<T> collection)
        {
            _collection = collection;
        }

        // Implement CollectionBase API by passing through to _collection
    }
}

他のヒント

おそらく、何が必要です。

public CollectionBase<Object> CreateCollection();

すべてのクラスは、直接的または間接的にオブジェクト・クラスから継承するので

それはの完全のナイーブだけど...

場合は、

私は実際にこれを行って、謝罪していません

public CollectionBase<Object> CreateCollection();

あなたは本当にそれが何になりたい場合は、あなただけいるICollectionを返すことができて、彼らが必要として、あなたの消費者は.Cast<ItemBase>()拡張メソッドを呼び出すことができます。

私が理解から、.NET 4.0で、あなたはCollectionBase<ItemBase>を返すことができるだろうが、私はまだベータ版でそれを試していません。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top