繁体   English   中英

是否调用IEnumerable.Cast <T> ()将基础类型更改为其他类型,还是保留基础类型?

[英]Does calling IEnumerable.Cast<T>() changes the underlying type to something else, or the underlying type preserved?

假设我有ISet<T> _set = new HashSet<T>();

现在,如果我这样做了: _set.Cast<TInterface>().Contains(obj, comparer); (其中T实现TInterface ),我是否失去HashSet<T>O(1)好处?

换句话说.Cast<T>()会将基础类型(在这种情况下为HashSet<T> )更改为其他类型,还是保留基础类型?

从逻辑上讲, HashSet<T>使用基于内部哈希表的哈希表,该哈希表是使用创建的比较器的哈希逻辑进行的,因此,当然不可能使用其他比较器对它进行元素包含测试,并且期望O( 1)性能。


也就是说,让我们针对您的特定情况更详细地研究一下事情:

Cast<T>方法如下所示(来自参考源):

  public static IEnumerable<TResult> Cast<TResult>(this IEnumerable source) {
            IEnumerable<TResult> typedSource = source as IEnumerable<TResult>;
            if (typedSource != null) return typedSource;
            if (source == null) throw Error.ArgumentNull("source");
            return CastIterator<TResult>(source);
        }

如您所见,如果源实现IEnumerable<TResult>它将直接直接返回源。 由于IEnumerable<>是协变接口,因此该测试将通过您的用例(假设具体类型实现了接口类型),并且哈希集将直接返回-一件好事,因为仍然希望其内部哈希表正在使用。

但是,您正在使用的Contains重载如下所示:

 public static bool Contains<TSource>(this IEnumerable<TSource> source, TSource value, IEqualityComparer<TSource> comparer)
        {
            if (comparer == null) comparer = EqualityComparer<TSource>.Default;
            if (source == null) throw Error.ArgumentNull("source");
            foreach (TSource element in source)
                if (comparer.Equals(element, value)) return true;
            return false;
        }

如您所见,它总是循环遍历整个集合以进行线性搜索,即O(n)。

因此,无论如何,整个运算都将是O(n)。

_set.Cast<TInterface>()将返回IEnumerable<TInterface>因此_set.Cast<TInterface>().Contains(obj, comparer); 不调用HashSet.Contains ,而是调用Enumerable.Contains扩展方法。

因此很显然,您不再需要O(1)运算。

如果需要O(1) ,则再次需要从中创建一个HashSet

   var newSet = new HashSet(_set.Cast<TInterface>(),comparer);
   newSet.Contains();

Cast方法返回一个IEnumerable,因此Contains方法将在IEnumerable而不是HashSet上进行操作。 因此,我认为您会失去HashSet的好处。 您为什么不进行比较中的演员表转换呢?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM