LINQ在实现IEnumerable<;T>;两次
本文关键字:gt 两次 lt IEnumerable LINQ 实现 | 更新日期: 2023-09-27 17:59:38
我的类实现了两次IEnumerable<T>
如果不每次都铸造hashtable
,如何让LINQ工作
我编写了自己的协变哈希表实现,它也继承自。NET的CCD_ 3。最终,它为T
实现了两次不同类型的IEnumerable<T>
。我隐式地实现了主可枚举接口,另一个显式地实现。类似这样的东西(伪代码):
class HashTable<TKey, TValue> :
...
IEnumerable<out IAssociation<out TKey, out TValue>>,
IEnumerable<out KeyValuePair<TKey, TValue>>
{
// Primary:
public IEnumerator<IAssociation<TKey, TValue>> GetEnumerator();
// Secondary:
IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator();
}
当我foreach
哈希表时,它会像预期的那样使用主可枚举值:
using System;
using System.Collections.Generic;
using System.Linq;
var hashtable = new HashTable<string, int>();
foreach (var kv in hashtable)
{
// kv is IAssociation<string, int>
}
现在我希望它在LINQ中做同样的事情,但它会向我抛出编译器错误,因为它不知道为扩展方法选择哪个接口:
var xs1 = from x in hashtable // <-- 1
select x;
var xs2 = hashtable.Select(x => x); // <-- 2
错误1:找不到源类型"HashTable"的查询模式的实现选择"未找到"。请考虑显式指定范围变量"x"的类型。
错误2:"HashTable"不包含"Select"的定义,并且找不到接受"HashTable"类型的第一个参数的扩展方法"Select"(是否缺少using指令或程序集引用?)
也许有一些接口或继承技巧我不知道?
对于那些询问的人来说,以下是完整的接口树:
using SCG = System.Collections.Generic;
public class HashTable<TKey, TValue>
: IKeyedCollection<TKey, TValue>, SCG.IDictionary<TKey, TValue>
public interface IKeyedCollection<out TKey, out TValue>
: ICollection<IAssociation<TKey, TValue>>
public interface ICollection<out T> : SCG.IEnumerable<T>
public interface IAssociation<out TKey, out TValue>
// .NET Framework:
public interface IDictionary<TKey, TValue>
: ICollection<KeyValuePair<TKey, TValue>>
public interface ICollection<T>
: IEnumerable<T>
现在你可以理解为什么我不能使KeyValuePair<TKey, TValue>
和IAssociation<TKey, TValue>
相同了。
在使用表达式作为方法调用的参数时,必须理解编译器没有"主要"answers"次要"接口实现的概念。就转换到IEnumerable<IAssociation<...>>
和IEnumerable<KeyValuePair<...>>
这两种类型而言,您的类型实现得同样好。这就是编译器需要更多信息的原因。
最简单的方法(IMO)是引入两种新特性:
public IEnumerable<IAssociation<TKey, TValue>> Associations { get { return this; } }
public IEnumerable<KeyValuePair<TKey, TValue>> KeyValuePairs { get { return this; } }
这意味着你可以很容易地具体化:
var query = from x in table.Associations
...;
或
var query = from x in table.KeyValuePairs
...;
这不仅有助于让编译器满意,也有助于任何试图读取代码的人。如果发现其中一个比另一个使用得更多,则可以始终使HashTable
只实现一个IEumerable<>
,并键入并保留另一个属性。