Dan*_*ker 14 c# linq generics collections ienumerable
我的班级实施了IEnumerable<T>两次.我怎样才能让LINQ无需hashtable每次都进行投射?
我编写了自己的协变哈希表实现,它也继承自.NET IDictionary<TKey, TValue>.最终,它实现了IEnumerable<T>两次不同的类型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();
}
Run Code Online (Sandbox Code Playgroud)
当我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>
}
Run Code Online (Sandbox Code Playgroud)
现在我希望它在LINQ中做同样的事情,但它在我身上编译错误,因为它不知道为扩展方法选择哪个接口:
var xs1 = from x in hashtable // <-- 1
select x;
var xs2 = hashtable.Select(x => x); // <-- 2
Run Code Online (Sandbox Code Playgroud)
错误1:无法找到源类型"HashTable"的查询模式的实现.找不到"选择".考虑明确指定范围变量'x'的类型.
错误2:'HashTable'不包含'Select'的定义,并且没有扩展方法'Select'接受类型为'HashTable'的第一个参数'(您是否缺少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>
Run Code Online (Sandbox Code Playgroud)
现在你可以看到为什么我不能做KeyValuePair<TKey, TValue>和IAssociation<TKey, TValue>相同.
Jon*_*eet 25
重要的是要理解,当使用表达式作为方法调用的参数时,编译器没有"主要"和"次要"接口实现的概念.就这些类型的转换而言,您的类型同时实现两者IEnumerable<IAssociation<...>>并且IEnumerable<KeyValuePair<...>>同样良好.这就是编译器需要更多信息的原因.
最简单的方法(IMO)将引入两个新属性:
public IEnumerable<IAssociation<TKey, TValue>> Associations { get { return this; } }
public IEnumerable<KeyValuePair<TKey, TValue>> KeyValuePairs { get { return this; } }
Run Code Online (Sandbox Code Playgroud)
这意味着你可以很容易地具体化:
var query = from x in table.Associations
...;
Run Code Online (Sandbox Code Playgroud)
要么
var query = from x in table.KeyValuePairs
...;
Run Code Online (Sandbox Code Playgroud)
这不仅有助于保持编译器的快乐 - 它还可以帮助任何尝试阅读代码的人.如果你发现你使用其中的一个多比对方多,你总是可以让HashTable只实现单一IEumerable<>和类型,并保持其他财产.
| 归档时间: |
|
| 查看次数: |
882 次 |
| 最近记录: |