Мой класс реализует 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();
}
Когда я 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" не содержит определения для "Выбрать" , и не может быть найден метод расширения "Выбрать" , принимающий первый аргумент типа "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>
Теперь вы можете понять, почему я не мог сделать теги KeyValuePair<TKey, TValue>
и IAssociation<TKey, TValue>
.