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 实例和 foo 中的列表/数据属性提供不同的数据类型。但是通用示例中的 T 将是相同的,并且只允许这样做:

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

foo.list 中的每个项目将再次具有一个可能属于不同类型的列表。到我编译时,MyClass我不知道列表/数据属性中将包含哪些数据类型或将有多少级别。如何构建这种灵活的结构?

4

4 回答 4

1

泛型旨在允许编译器对类型使用进行检查,并且它们还提供了一些漂亮的额外好处。

您所描述的内容无法通过泛型实现,如果每次您使用list可能不同类型的列表进行更新,那么泛型无法帮助您。

但是,如果这些类型中的每一个都共享一个通用的基本类型或共享一个通用接口,那么您可以将其用作您T的列表,这样您就可以使用它们。

但是,如果每个实例MyClass只允许一种类型的列表,MyClass<?>那么您可以MyClass这样修改:

public class MyClass<T, TList>
{
    private List<MyClass<T, TList>> list;
    private T data;
}
于 2013-04-05T12:05:19.053 回答
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 中添加第二种类型。

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, GetBool, GetString。然后我想要一个模板Add来实例化适当的具体类并将其添加到我的向量中。我不确定它是否会起作用,但它遵循以下原则:

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 回答