C# 调用IEnumerable.Cast<;T>;()将基础类型更改为其他类型,还是保留基础类型?
假设我有C# 调用IEnumerable.Cast<;T>;()将基础类型更改为其他类型,还是保留基础类型?,c#,linq,linq-to-objects,C#,Linq,Linq To Objects,假设我有ISet\u set=newhashset() 现在如果我这样做:\u set.Cast()包含(obj,comparer)(其中T实现TInterface),我是否失去了HashSet的O(1)优势 换句话说,.Cast()ing是否将基础类型(HashSet在本例中)更改为其他类型,或者基础类型是否保留?Cast方法返回一个IEnumerable,因此Contains方法将对IEnumerable而不是HashSet进行操作。所以我认为你失去了HashSet的好处。为什么不改为在比较
ISet\u set=newhashset()代码>
现在如果我这样做:\u set.Cast()包含(obj,comparer)
(其中T
实现TInterface
),我是否失去了HashSet
的O(1)
优势
换句话说,.Cast()
ing是否将基础类型(HashSet
在本例中)更改为其他类型,或者基础类型是否保留?Cast方法返回一个IEnumerable,因此Contains方法将对IEnumerable而不是HashSet进行操作。所以我认为你失去了HashSet的好处。为什么不改为在比较中执行强制转换?强制转换方法返回IEnumerable,因此Contains方法将对IEnumerable而不是哈希集进行操作。所以我认为你失去了HashSet的好处。为什么不改为在compared中执行强制转换?\u set.cast()
将返回一个IEnumerable
so\u set.cast().Contains(obj,comparer)
不调用,而是调用扩展方法
所以很明显你不再得到O(1)
操作了
如果需要O(1)
,则需要再次从中创建一个HashSet
var newSet = new HashSet(_set.Cast<TInterface>(),comparer);
newSet.Contains();
var newSet=newhashset(_set.Cast(),comparer);
newSet.Contains();
\u set.Cast()
将返回一个IEnumerable
so\u set.Cast().Contains(对象、比较器)
不调用,而是调用扩展方法
所以很明显你不再得到O(1)
操作了
如果需要O(1)
,则需要再次从中创建一个HashSet
var newSet = new HashSet(_set.Cast<TInterface>(),comparer);
newSet.Contains();
var newSet=newhashset(_set.Cast(),comparer);
newSet.Contains();
从逻辑上讲,哈希集
使用一个内部哈希表,该哈希表基于创建它时使用的比较器的哈希逻辑,因此当然不可能使用不同的比较器对其进行元素包含测试并期望O(1)性能
也就是说,让我们更详细地了解您的特定场景:
Cast
方法如下所示(来自参考源):
公共静态IEnumerable强制转换(此IEnumerable源代码){
IEnumerable typedSource=源为IEnumerable;
如果(typedSource!=null)返回typedSource;
if(source==null)抛出错误.ArgumentNull(“source”);
返回迭代器(源);
}
如您所见,如果源代码实现了IEnumerable
,它只会直接返回源代码。由于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;
}
公共静态bool包含(此IEnumerable源、TSource值、IEqualityComparer比较器)
{
如果(comparer==null)comparer=EqualityComparer.Default;
if(source==null)抛出错误.ArgumentNull(“source”);
foreach(源中的TSource元素)
if(comparer.Equals(element,value))返回true;
返回false;
}
如您所见,它总是通过集合循环到线性搜索,即O(n)
因此,整个操作都将是O(n)从逻辑上讲,哈希集
使用一个内部哈希表,该哈希表基于创建时使用的比较器的哈希逻辑,因此当然不可能使用不同的比较器对其进行元素包含测试,并期望O(1)性能
也就是说,让我们更详细地了解您的特定场景:
Cast
方法如下所示(来自参考源):
公共静态IEnumerable强制转换(此IEnumerable源代码){
IEnumerable typedSource=源为IEnumerable;
如果(typedSource!=null)返回typedSource;
if(source==null)抛出错误.ArgumentNull(“source”);
返回迭代器(源);
}
如您所见,如果源代码实现了IEnumerable
,它只会直接返回源代码。由于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;
}
公共静态bool包含(此IEnumerable源、TSource值、IEqualityComparer比较器)
{
如果(comparer==null)comparer=EqualityComparer.Default;
if(source==null)抛出错误.ArgumentNull(“source”);
foreach(源中的TSource元素)
if(comparer.Equals(element,value))返回true;
返回false;
}
如您所见,它总是通过集合循环到线性搜索,即O(n)
因此,整个操作都将是O(n)请参阅每次我想测试是否包含某个对象时重新创建新的哈希集
,这会造成很大的开销,但如果您想测试一行中的1000个项,则重新创建哈希集
是一个更好的选择。不要这样认为:在最坏的情况下,迭代直到找到为止只有O(n)(如果你在第二个索引中找到它,那就是O(2)…,而在任何容器中添加N个项目总是O(N)-这总是最糟糕的情况,我想你误解了我的评论。我说如果你想检查1000个项目是否以O(N)
*1000的顺序存在,但是如果你只创建一个Ha