是否可以拥有Object <t>类的集合?

时间:2018-04-19 19:29:42

标签: c#

我有一个想要放入List或Collection的对象。如果没有指定T,有没有办法做到这一点?

我想做这样的事情:List<CommonProperty<T>>

以下是供参考的对象:

internal class CommonProperty<T>
{
    public string Name { get; set; }
    public PropType Type { get; set; }
    public List<T> PossibleValues { get; set; }
    private T _value;
    public T Value
    {
        get { return _value; }
        set
        {
            if (!_value.Equals(value))
            {
                _value = value;
            }
        }
    }
}

3 个答案:

答案 0 :(得分:1)

不,你不能使用这样的开放泛型类型。

List<CommonProperty<T>>已经是类型参数的上下文中,您可以拥有T

public class Foo<T>
{
    static void Bar()
    {
        // This is fine, but is not what you're looking for - it uses
        // the type parameter T as the type argument
        List<CommonProperty<T>> list = new List<CommonProperty<T>>();
    }
}

通常,此处的解决方案是使用非泛型基类或接口,泛型类或接口派生自:

// Consider making it abstract
internal class CommonProperty
{
    public string Name { get; set; }
    public PropType Type { get; set; }
}

internal class CommonProperty<T> : CommonProperty
{
    public List<T> PossibleValues { get; set; }
    private T _value;
    public T Value
    {
        get => _value;
        set
        {
            // TODO: Is this really necessary?
            if (!_value.Equals(value))
            {
                _value = value;
            }
        }
    }
}

然后,您可以创建一个List<CommonProperty> ...但请注意,完全有可能您最终会得到一个不是CommonProperty<T>的元素

List<CommonProperty>您可以检索所有属性的名称和类型 - 但是这些值在没有强制转换为特定类型的情况下也无法使用。你可以 在基类中有一个abstract object Value { get; set; }属性,然后可能会在派生类中重写 - 但是不清楚它是否必要或有帮助在你的用例中。

答案 1 :(得分:1)

我认为最接近的是使用CommonProperty而不是Object定义一个与未键入的(特定)T匹配的界面。然后让你的CommonProperty<T>实现该接口。现在,您可以使用列表中的界面。

但这并不好。你将失去许多不错的类型检查,并且必须做更多的投射。如果这是你使用这些对象的主要方式,那就完全没有太多的通用类了。

答案 2 :(得分:0)

不可能将使用不同类型参数实例化的泛型混合物放入同一个集合中。这样的集合无论如何都没有用,因为调用者应该在编译时为每个项目提供T

假设你可以做你想做的事,即

// imagine that you could do this
List<CommonProperty<T>> mixedList = GetAllProperties(); 

一旦开始使用该列表中的项目,即

,您将被迫提供T
foreach (CommonProperty<T> prop in mixedList) {
    ... //             ^^^
    ... // Here you would need to specify T, but you don't know which one
}

换句话说,这样的列表将无法使用。

另一方面,特定类型的属性列表很有用:

List<CommonProperty<string>> stringPropList = GetPropertiesOfType<string>();
foreach (CommonProperty<string> prop in stringPropList ) {
    ...
}

因此,问题的一个解决方案是构建GetPropertiesOfType<T>方法,返回List<CommonProperty<T>>绑定到来自调用者的T类型。

另一种方法是使CommonProperty非泛型,让调用者在运行时检查类型:

internal class CommonProperty {
    public string Name { get; set; }
    public PropType Type { get; set; }
    public List<T> GetPossibleValues<T> { get; set; }
    private object _value;
    public T GetValue<T>() {
        return (T)_value;
    }
    public void SetValue<T>(T val) {
        _value = val;
    }
}