在.NET(C#或VB.NET)中,非泛型类是否可以包含泛型列表?

8
希望有人能帮助我理解是否/如何可能实现以下内容。
在这种情况下,想象一下您正在尝试建模类似于电子表格或数据库中的网格,但是每个列中的数据只能为一个数据类型。
例如:第1列只能包含整数。
我创建了一个通用类来模拟列结构,它看起来像这样:
public class CollectionColumn<T>
{
private string _name;
private string _displayName;

private List<T> _dataItems = new List<T>();

public string Name {
    get { return _name; }
    set { _name = value; }
}

public string DisplayName {
    get { return _displayName; }
    set { _displayName = value; }
}


public List<T> Items {
    get { return _dataItems; }
    set { _dataItems = value; }
}
}

现在我想要做的是为各种列(可能是CollectionColumn,CollectionColumn等)拥有自己的属性的容器,但我不确定如何做到这一点,在我不知道它们类型时仍然可以访问列和其中的数据。
这是一个.NET 2.0项目,因此像动态之类的东西不起作用,也许是对象列表?我也不确定是否有办法使用接口来实现这一点。
public class ColumnCollection
{
public int Id { get; set; }
public string ContainerName { get; set; }

private List<CollectionColumn<T>> _columns;
public List<CollectionColumn<T>> Columns {
    get { return _columns; }
    set { _columns = value; }
}

}

我想要做的是向ColumnCollection的Columns集合中添加不同的CollectionColumn,这样就可以包含多种类型的数据列。
非常感谢您的帮助。

你真的想要暴露这样的 List<T> 吗?通常,如果一个类将要公开一个类类型属性,它应该被视为标识而不是包含它所引用的对象,或者它应该是对一个不可变对象的可能可变的引用,或者它应该是对一个可能可变对象的不可变引用。从外观上看,你的列将把 List<T> 的内容视为自己的(因此点1不符合),引用是可变的(点2),而 List<T> 是可变的(点3)。 - supercat
那是一个危险的模式,因为一个设置引用指向其自己列表的对象无法知道是否会有其他对象尝试改变该引用所指向的列表,也无法让任何想要改变该对象持有的列表的对象知道是否有任何正在期望它不会改变的内容持有对该列表的引用。 - supercat
1个回答

11

这是一个相当常见的问题。您需要做的是声明一个非泛型基类,让您的泛型类继承它,或者声明一个非泛型接口,让您的泛型类实现它。然后您可以创建该类型的集合。

例如,

public abstract class CollectionColumnBase
{
    private string _name;
    private string _displayName;

    public string Name {
        get { return _name; }
        set { _name = value; }
    }

    public string DisplayName {
        get { return _displayName; }
        set { _displayName = value; }
    }

    public abstract object GetItemAt(int index);
}

public class CollectionColumn<T> : CollectionColumnBase
{
    private List<T> data = new List<T>();

    public overrides object GetItemAt(int index)
    {
        return data[index];
    }

    public List<T> Items
    {
        get { return data; }
        set { data = value; }
    }
}

public class ColumnCollection
{
    public int Id { get; set; }
    public string ContainerName { get; set; }

    private List<CollectionColumnBase> _columns;
    public List<CollectionColumnBase> Columns {
        get { return _columns; }
        set { _columns = value; }
    }
}

谢谢Adam。我刚刚将CollectionColumnBase变成了抽象类,并在ColumnCollection构造函数中新建了一个CollectionColumnBase列表,这样它就永远不会为空了。再次感谢! - jon333
@jon333:是的,你需要做这些事情。我会修改答案的,谢谢! - Adam Robinson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接