2

私は次のようなカスタムクラス(と呼びましょうMyClass)を持っています:

public class MyClass
{
    private List<MyClass> list;
    private object data;
}

ただし、プロパティを取り除き、object代わりにジェネリック クラスを使用したいと考えています。だから、このようなもの:

public class MyClass<T>
{
    private List<MyClass<T>> list;
    private T data;
}

ただし、次の動作が必要です。

MyClass<Foo> foo = new MyClass<Foo>;
foo.list = new List<MyClass<Bar>>;

したがって、foo-instance と foo のリスト/データ プロパティに異なるデータ型を持たせる必要があります。ただし、一般的な例の T は同じであり、これのみを許可します。

MyClass<Foo> foo = new MyClass<Foo>;
foo.list = new List<MyClass<Foo>>;

foo.list の各項目には、異なるタイプのリストが含まれます。コンパイルするまでMyClassに、リスト/データプロパティに含まれるデータ型やレベル数についてはわかりません。この柔軟な構造をどのように構築できますか?

4

4 に答える 4

1

ジェネリックは、コンパイラが型の使用状況をチェックできるように設計されており、いくつかの気の利いた追加の利点も提供します。

あなたが説明したことはlist、潜在的に異なるタイプのリストで更新するたびにジェネリックが役に立たない場合、ジェネリックでは達成できません。

ただし、これらの型のそれぞれが共通の基本型を共有するか、共通のインターフェイスを共有する場合は、それをTリストとして使用でき、それらを使用できるようになります。

ただし、 の各インスタンスがMyClassのリストの 1 つのタイプのみを許可する場合は、次のMyClass<?>ように修正できますMyClass

public class MyClass<T, TList>
{
    private List<MyClass<T, TList>> list;
    private T data;
}
于 2013-04-05T12:05:19.053 に答える
1

この目標は、1 つのクラスだけでは達成できません。子を持つ各レベルに対して 1 つのジェネリック基本クラス、子を持たない最下位レベルに対して 1 つの基本クラス、および階層レベルごとに 1 つの派生クラスを構築する必要があります。

基本クラスは次のようになります。

public class MyClass<TData>
{
    public TData Data { get; set; }
}

public class MyClass<TData, TDataChildren, TChildren> : MyClass<TData>
    where TChildren : MyClass<TDataChildren>
{
    public List<TChildren> List { get; set; }
}

レベルごとの派生クラスは次のようになります。

public class Level0 : MyClass<Foo, Bar, Level1> { }

public class Level1 : MyClass<Bar, Fubar, Level2> { }

public class Level2 : MyClass<Fubar> { }

使用法:

var root = new Level0();
root.Data = new Foo();
root.List = new List<Level1>
{
    new Level1()
    {
        Data = new Bar(),
        List = new List<Level2>
        {
            new Level2()
            {
                Data = new Fubar()
            }
        }
    }
};
于 2013-04-05T12:09:13.960 に答える
0

MyClass に 2 番目のタイプを追加します。

public class MyClass<T, G>
{
    private List<MyClass<G, T>> list;
    private T data;
}

これは、リスト内のネストされたリストのタイプを気にしないことを前提としています。

しかし、抽象的なデータだけではわかりにくいので、コードの有用性についてもう少し詳しく説明していただけますか。

于 2013-04-05T12:05:29.323 に答える
0

現在、C++ で非常によく似たものを実装しようとしていますが、同じ問題が発生しています。テンプレートの問題は、それらが厳密に型指定MyClass<foo>されており、完全に異なる無関係な型として扱われることMyClass<bar>です。

私が今遊んでいるのは、、、、のような純粋な仮想メソッドを持つ抽象クラスを作成GetIntすることGetDoubleです。次に、適切な具象クラスをインスタンス化してベクターに追加するテンプレートを作成したいと考えています。それが機能するかどうかはわかりませんが、次の行に沿っています。GetBoolGetStringAdd

class Data
{
public:
    template<typename T> Add(const std::string& key, const T& val)
    {
         Data* pData = NULL;

         //test the type using std::numeric_limits to figure out which concrete
         //type to use.

         m_mapValues[key] = pData;
    }

protected:

    virtual int GetInt() const = 0;
    virtual unsigned int GetUINT() const = 0;
    virtual std::string GetString() const = 0;
    //blah blah more types that you want to handle

private:

    std::map<std::string,Data*> m_mapValues;
};

class UINTData : public Data
{
    //implement pure virtual methods.
}

これは明らかに不完全ですが、いくつかのアイデアを得ることができれば幸いです。

于 2013-04-05T12:19:33.130 に答える