我有一个界面和两个类。
public interface IMyInterface { }
public class A : IMyInterface { }
public class B : IMyInterface { }
我有一个通用的方法,
private List<T> GetList<T>(DataTable table)
where T : class, IMyInterface
{
...
}
应根据DataTable中的数据返回一个对象列表。所以,我在这个方法中创建了一个列表,我想在最后返回。我以为我可以做到以下几点,
private List<T> GetList<T>(DataTable table)
where T : class, IMyInterface
{
List<T> myList = new List<T>;
// Now I thought I could easily add Objects based on T because,
// both classes implement the interface
if (typeof(T) == typeof(B))
{
myList.Add(new B());
}
else
{
myList.Add(new A());
}
return myList;
}
但是编译器告诉我“参数类型A(B)不是可以指定的”!为什么不可分配?
好的,我也可以这样做,
private List<T> GetList<T>(DataTable table)
where T : class, IMyInterface
{
List<IMyInterface> myList = new List<IMyInterface>;
// Now I can assign the Object's :)
if (typeof(T) == typeof(B))
{
myList.Add(new B());
}
else
{
myList.Add(new A());
}
return myList as List<T>;
}
编译器没有抱怨,但return子句的结果始终为null。确保myList
中有值。演员似乎失败了。有人请帮我更优雅地解决这个问题。
答案 0 :(得分:5)
一种方法是添加new()
约束。限制是您需要类型参数T的公共无参数构造函数。
private static List<T> GetList<T>(DataTable table) where T : class, IMyInterface, new()
{
List<T> myList = new List<T>();
T instance = new T();
//access anything defined in `IMyInterface` here
myList.Add(instance);
return myList;
}
答案 1 :(得分:2)
我不明白你在这里要做什么。为什么你甚至需要泛型?
你最初是以正确的方式,从同一个界面派生你的类型,所以要使用它。声明您的列表List<IMyInterface>
,只需按原样添加对象即可。
如果以后你实际上需要具有具体A
或B
类型的可枚举的物理表示,那么你有OfType<>()
和Cast<>()
,尽管它显示了你的多态性首先做错了。
答案 2 :(得分:1)
private List<T> GetList<T>(DataTable table) where T : class, IMyInterface, new()
{
return new List<T>(){ new T() };
}
答案 3 :(得分:1)
在将对象添加到List:
之前,您应该先强制转换对象 private static List<T> GetList<T>(DataTable table) where T : class, MyInterface
{
List<T> myList = new List<T>();
//Now i thought i can easily add Objects based on T, because both classes
//implement the interface
if (typeof (T) == typeof (B))
{
// use of 'as' operator
myList.Add(new B() as T);
}
else
{
myList.Add(new A() as T);
}
return myList;
}
但无论如何,我没有得到一点,你想要实现的目标。
同样myList as List<T>
肯定会产生null
,因为您无法使用as
运算符强制转换通用集合,因为List<T>
未声明为Covariant。您应该明确调用.Cast<T>()
方法来创建新集合。
答案 4 :(得分:1)
我猜你真的想做点什么,
public IList<T> GetList<T>(
DataTable table,
Func<DataRow, T> extractor)
{
var result = new T[table.Rows.Count];
for (var i = 0; i < table.Rows.Count; i++)
{
result[i] = extractor(table.Rows[i]);
}
return result;
}
extractor
是将DataRow
转换为T
的代表。
这比你想象的更简单,
// referencing System.Data.DataSetExtensions
var list = GetList(
data,
row => new A
{
Id = row.Field<int>("id"),
...
});
list
将是IList<A>
等其他类型。
答案 5 :(得分:0)
试试这个:
private List<T> GetList<T>(DataTable table) where T : class, IMyInterface {
List<T> myList = new List<T>();
if (typeof(T) == typeof(B)) {
myList.Add((T)new B());
}
else {
myList.Add((T)new A());
}
return myList
}
答案 6 :(得分:0)
仅适用于A类和B类
static List<T> GetList<T>(DataTable table) where T : class, IMyInterface
{
List<T> myList = new List<T>();
IMyInterface obj;
if (typeof(T) == typeof(B))
{
obj = new B();
}
else
{
obj = new A();
}
myList.Add((T)obj);
return myList;
}