C# 泛型方法无法创建 List<T>
C# generic method can't create List<T>
我有一个接口和两个 类。
public interface IMyInterface { }
public class A : IMyInterface { }
public class B : IMyInterface { }
我有一个通用方法,
private List<T> GetList<T>(DataTable table)
where T : class, IMyInterface
{
...
}
这应该 return 基于 DataTable 中数据的对象列表。所以,我在这个方法中创建了一个列表,我想在最后 return 。我以为我可以做到以下几点,
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;
}
但是编译器告诉我 "Argument type A (B) is not assigneable"!为什么不能分配?
好的,或者我可以执行以下操作,
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 子句的结果始终为空。 myList
中肯定有值。演员似乎失败了。请有人帮我更优雅地解决这个问题。
试试这个:
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
}
一种方法是添加 new()
约束。限制是你需要一个 public 类型参数 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;
}
添加一个new
constraint
private List<T> GetList<T>(DataTable table) where T : class, IMyInterface, new()
{
return new List<T>(){ new T() };
}
我不明白你想在这里做什么。为什么你甚至需要泛型?
你一开始走的路是对的,从同一个接口派生你的类型,所以好好利用它。声明您的列表 List<IMyInterface>
并按原样简单地添加您的对象。
如果稍后您确实需要具有具体 A
或 B
类型的可枚举的物理表示,您可以使用 OfType<>()
和 Cast<>()
,尽管它显示你的多态性一开始就做错了。
在将对象添加到列表之前,您应该转换对象:
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>()
方法来创建新集合。
仅适用于 class 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;
}
我猜你真的想做这样的事情,
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>
。
我有一个接口和两个 类。
public interface IMyInterface { }
public class A : IMyInterface { }
public class B : IMyInterface { }
我有一个通用方法,
private List<T> GetList<T>(DataTable table)
where T : class, IMyInterface
{
...
}
这应该 return 基于 DataTable 中数据的对象列表。所以,我在这个方法中创建了一个列表,我想在最后 return 。我以为我可以做到以下几点,
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;
}
但是编译器告诉我 "Argument type A (B) is not assigneable"!为什么不能分配?
好的,或者我可以执行以下操作,
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 子句的结果始终为空。 myList
中肯定有值。演员似乎失败了。请有人帮我更优雅地解决这个问题。
试试这个:
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
}
一种方法是添加 new()
约束。限制是你需要一个 public 类型参数 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;
}
添加一个new
constraint
private List<T> GetList<T>(DataTable table) where T : class, IMyInterface, new()
{
return new List<T>(){ new T() };
}
我不明白你想在这里做什么。为什么你甚至需要泛型?
你一开始走的路是对的,从同一个接口派生你的类型,所以好好利用它。声明您的列表 List<IMyInterface>
并按原样简单地添加您的对象。
如果稍后您确实需要具有具体 A
或 B
类型的可枚举的物理表示,您可以使用 OfType<>()
和 Cast<>()
,尽管它显示你的多态性一开始就做错了。
在将对象添加到列表之前,您应该转换对象:
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>()
方法来创建新集合。
仅适用于 class 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;
}
我猜你真的想做这样的事情,
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>
。