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> 并按原样简单地添加您的对象。

如果稍后您确实需要具有具体 AB 类型的可枚举的物理表示,您可以使用 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>