C# LINQ在实现IEnumerable时会感到困惑<;T>;两次

C# LINQ在实现IEnumerable时会感到困惑<;T>;两次,c#,linq,generics,collections,ienumerable,C#,Linq,Generics,Collections,Ienumerable,我的类实现了两次IEnumerable如何让LINQ在每次都不使用哈希表的情况下工作? 我编写了自己的协变哈希表实现,它也继承了.NET的IDictionary。最终,它使用T的不同类型实现了两次IEnumerable。我隐式地实现了主可枚举接口,而显式地实现了另一个接口。类似这样的内容(伪代码): 现在我希望它在LINQ中做同样的事情,但它向我抛出编译器错误,因为它不知道为扩展方法选择哪个接口: var xs1 = from x in hashtable // <--

我的类实现了两次
IEnumerable
如何让LINQ在每次都不使用哈希表的情况下工作?


我编写了自己的协变哈希表实现,它也继承了.NET的
IDictionary
。最终,它使用
T
的不同类型实现了两次
IEnumerable
。我隐式地实现了主可枚举接口,而显式地实现了另一个接口。类似这样的内容(伪代码):

现在我希望它在LINQ中做同样的事情,但它向我抛出编译器错误,因为它不知道为扩展方法选择哪个接口:

var xs1 = from x in hashtable          // <-- 1
          select x;

var xs2 = hashtable.Select(x => x);    // <-- 2

var xs1=来自哈希表中的x//x);// 重要的是要理解,在使用表达式作为方法调用的参数时,编译器没有“主要”和“次要”接口实现的概念。就转换到这些类型而言,您的类型同样可以很好地实现
IEnumerable
IEnumerable
。这就是编译器需要更多信息的原因

最简单的方法(IMO)是引入两个新属性:

public IEnumerable<IAssociation<TKey, TValue>> Associations { get { return this; } }
public IEnumerable<KeyValuePair<TKey, TValue>> KeyValuePairs { get { return this; } }


这不仅有助于让编译器感到高兴,还可以帮助任何试图阅读代码的人。如果您发现其中一个比另一个使用得多,则始终可以使
哈希表
只实现一个
IEumerable
,然后键入并保留另一个属性。

您是否尝试手动指定
选择
的属性?听起来它很难推断它们。特别是,您需要手动指定
TSource
,但一旦您指定了一个,我认为您需要同时指定这两个。不幸的是,这将使您无法返回匿名类型,而无需一些烦人的解决方法。您是否可以包括
哈希表
的其余继承/接口?它告诉您该怎么做,至少对于第一个错误是这样的。您必须明确说明“x”是什么类型:从哈希表中的IASociation x选择x;为什么其中一个使用
iasociation
,另一个使用
KeyValuePair
?我希望它们都使用相同的类型。您也可以使用一个适配器类,该类将知道如何将IAssociation转换为KeyValuePair,反之亦然(通过隐式运算符),然后使哈希表从中继承。但是我宁愿选择Jon Skeet Solutions,因为没有其他方法可以通过直接实现它们来满足编译器的要求。@Antonijn:是的,可以通过显式指定类型参数来满足编译器的要求。。。
var xs1 = from x in hashtable          // <-- 1
          select x;

var xs2 = hashtable.Select(x => x);    // <-- 2
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>
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
            ...;