我有一个想要放入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;
}
}
}
}
答案 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;
}
}