c# - 如何编写一个将不同类型作为参数的泛型方法?

标签 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);
    }
}

如果 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

如果 IEnumerable 的类型是 T 类型的子类(或实现接口(interface)),我该如何修改我的扩展方法才能执行类似的操作?

最佳答案

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

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

一些注意事项:

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

关于c# - 如何编写一个将不同类型作为参数的泛型方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1753920/

相关文章:

c# - 在 EPPlus 中将地址引用样式 A1 转换为样式 R1C1

c# - C# 中 SQL UDT 类型参数传递

java - super 行为异常的通配符

c# - LINQ 在两次实现 IEnumerable<T> 时感到困惑

c# - 为什么这个 Actor 是不可能的?

javascript - 如何在 HTML 属性内的函数调用中将变量作为参数传递?

c# - 将 Azure SQL 数据库连接到 ASP.NET 项目

asp.net-mvc-3 - enctype = "multipart/form-data"的表单发布导致参数无法传递

java - 小服务程序和 JSP : How to send parameters with a link

c# - 在 C# 中使用 WIA 生成照片质量扫描