【问题标题】:How do I write a generic extension method to convert a List to a HashSet using HashSet.AddRange()?如何编写通用扩展方法以使用 HashSet.AddRange() 将 List 转换为 HashSet?
【发布时间】:2010-12-08 02:53:04
【问题描述】:

HashSet 没有 AddRange 方法,所以我想为它写一个扩展方法。这就是我所拥有的:

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

我有一个基类 Media 和一个派生类 Photo。这是我想要工作的代码:

var photos = new List<Photo>();
var media = new HashSet<Media>();
media.AddRange(photos);

但是,编译器告诉我,当我尝试使用AddRange() 时,它无法将List&lt;Photo&gt; 转换为IEnumerable&lt;Media&gt;。我很确定这是因为我在扩展方法中有IEnumerable&lt;T&gt;,但是我如何编写它以使类型与AddRange&lt;T&gt;中的类型不同?

【问题讨论】:

    标签: c# generics extension-methods hashset


    【解决方案1】:

    又一个泛型差异问题。您需要调用Cast&lt;Media&gt; 扩展方法将IEnumerable&lt;Photo&gt; 转换为IEnumerable&lt;Media&gt;,然后您的AddRange 实现的签名才能接受它。

    或者,您可以声明

    AddRange<T, U>(ICollection<T>, IEnumerable<U>) where U : T
    

    作为在签名中产生正确差异的解决方法。

    【讨论】:

    • 当您说 Cast&lt;Media&gt; 时,您是说自己编写还是 .NET Framework 中包含的东西?
    • 在 System.Linq 命名空间中的 .NET 框架中作为 IEnumerable 上的扩展方法。
    • 哦,没关系,我刚找到它。我试图使用 Cast(Blahblah) 而不是 Blahblah.Cast.
    【解决方案2】:

    实际上,HashSet&lt;T&gt; 可能没有AddRange 方法,但它有一个UnionWith 方法,这在语义上就是您要查找的。名称的不同反映了它过滤掉重复项的事实。如果您只想将集合复制到HashSet 中,它还有一个以IEnumerable&lt;T&gt; 作为参数的构造函数。

    在一般情况下,上述建议使用通用约束(“where T : U”)的答案是正确的。

    【讨论】:

    • 很好,我不知道。结合 Jeffrey 的Cast&lt;Media&gt; 回答,这意味着我可以摆脱我的扩展方法!
    • 补充一点:实际方法是Union,而不是UnionWith,它返回一个IEnumerable。毕竟我必须使用扩展方法,因为我需要添加到 HashSet。
    • 有一个名为 Union 的 IEnumerable 扩展方法,您可以使用它来取任意两个序列的并集,但如果您已经有一个 HashSet,它有一个单独的方法, UnionWith,效率更高,因为它扩展了您现有的集合,而不是分配一个全新的集合。
    猜你喜欢
    • 2013-03-07
    • 2021-11-24
    • 1970-01-01
    • 1970-01-01
    • 2011-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多