【问题标题】:Using base.Any(..) the warning is: 'HashSet' does not contain a definition for 'Any'使用 base.Any(..) 警告是:“HashSet”不包含“Any”的定义
【发布时间】:2011-04-19 22:20:00
【问题描述】:

一个类从 HashSet 继承来获得一组独特的对象,使用自定义 EqualKeys(T x, T y) 检查而不是 IEqualityComparer

public class UniqueSet<T> : HashSet<T> where T : IKey
{
    public new void Add(T item)
    {
         // .. check item for null, empty key etc.

          if (base.Any(t => UniqueSet<T>.EqualKeys(t, item)))
          {
             throw new ArgumentException(..);
          }
          if (!base.Add(item)) throw new ArgumentException(..);
     }

    private static bool EqualKeys(T x, T y) 
    {
       return ((IKey)x).Key.Equals(((IKey)y).Key, StringComparison.CurrentCultureIgnoreCase);
    }
}

代码无法编译,因为我必须将 base.Any 替换为 this.Any
恐怕我不明白这是为什么?

【问题讨论】:

    标签: c# hashset


    【解决方案1】:

    “Any”是一个扩展方法,而不是HashSet&lt;T&gt; 的方法。它在基类型上不存在,因此您不能在基类型上显式调用它。当你用“this.Any”调用它时,重载解析代码在“this”的类型上找不到“Any”,所以它开始寻找扩展方法,并找到一个。

    不是你的问题,但我还是要提一下:如果你添加到已经有这样一个元素的集合中,为什么要throw?为什么不直接让它成为无操作呢?通过 throw,您要求 Add 的调用者知道元素是否已经在集合中,这似乎是一个繁重的要求。

    【讨论】:

    • 另请参阅此问题:stackoverflow.com/questions/3510964/…
    • 我明白了,我没有注意到工具提示中的“(扩展名)”前缀!但是为什么显式使用基类型与显式使用 this 类型不同呢? “它”也可以从基类中寻找扩展方法并找到一个?可能在上面的链接中回答了..
    • 我对你的问题的回答:这个类更多的是一个内部的东西:开发人员永远不应该添加重复项,知道这一点很重要,因此我抛出了。为了简单起见,我不希望我的对象实现 Equals、HashCode 等。
    • @Gerard:当你使用“base”时,你正在挥舞着一面大红旗,上面写着“嘿!我正在这里进行非虚拟调度!”这就是它的目的:专门调用基类上的方法。当您明确表示要调用基类上的方法时,我们会在基类上寻找方法。将“base”与不在基类上的方法一起使用几乎可以肯定是一个错误,因此我们将其标记为错误,而不是默默地允许错误。
    【解决方案2】:

    因为HashSet&lt;T&gt; 没有实现Any()Any()IEnumerable&lt;T&gt; 的扩展方法。当您使用 base 时,您是在显式引用基类型而不是它的扩展方法。

    【讨论】:

    • 或者.Any() 是来自static class Enumerable 的扩展方法,因为这就是“转到定义”结束的地方(还是一样)? HashSet 如何找到这个静态类 - 它在另一个命名空间中?
    • @Gerard - Enumerable 是定义在IEnumerable&lt;T&gt; 上操作的扩展方法的静态类。
    猜你喜欢
    • 2011-07-03
    • 2020-08-20
    • 2015-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-26
    • 2018-09-24
    • 2020-03-31
    相关资源
    最近更新 更多