[英]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.