如何编写将不同类型作为参数的泛型方法?

Dan*_* T. 2 c# generics parameters extension-methods

我有以下扩展方法将一个集合中的元素添加到另一个集合:

public static void AddRange<T>(this ICollection<T> collection, IEnumerable<T> list)
{
    foreach (var item in list)
    {             
        collection.Add(item);
    }
}
Run Code Online (Sandbox Code Playgroud)

如果IEnumerable列表与我试图将其添加到的ICollection的类型相同,则此方法可以正常工作.但是,如果我有这样的事情:

var animals = new List<Animal>();
var dogs = new List<Dog>(); // dog is a subclass of animal
animals.AddRange(dogs); // this line has a compiler error, it can't infer the type
Run Code Online (Sandbox Code Playgroud)

如果IEnumerable的类型是T类型的子类(或实现接口),如何修改我的扩展方法以便能够执行此类操作?

Cra*_*ker 5

这个方法会给你你想要的:

public static void AddRange<A,B>(
  this ICollection<A> collection, 
  IEnumerable<B> list)
    where B: A
{
    foreach (var item in list)
    {
        collection.Add(item);
    }
}
Run Code Online (Sandbox Code Playgroud)

几个笔记:

  1. 唯一可行的方法是使用从A派生的B类型.例如,Dog是Animal的子类,因此AddRange将起作用.这由"where B:A"条款强制执行.如果没有这个,ICollection.Add()调用将因为B的不兼容类型被传递到期望A的ICollection而失败.
  2. 在Animal类型层次结构中,没有太多需要将A的类型限制为任何东西; 扩展方法可以在任何一种类型派生自另一种类型的地方使用.
  3. 这不是编译器无法推断类型的问题.即使您在任何地方明确传递了A和B的类型,您仍然会遇到编译器错误.