私のクラスはIEnumerable<T>
2 回実装します。毎回キャストせずにLINQを動作させるにはどうすればよいですか?hashtable
.NET の .NET からも継承する独自の共変ハッシュテーブル実装を作成しIDictionary<TKey, TValue>
ました。最終的に、IEnumerable<T>
の異なる型で 2 回実装し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>
。