Meine Klasse implementiert IEnumerable<T>
zweimal. Wie kann ich LINQ zu arbeiten, ohne hashtable
jedes Mal zu werfen?LINQ verwirrt bei der Implementierung von IEnumerable <T> zweimal
Ich schrieb meine eigene covariant hashtable Implementierung, die auch von .NET ist erbt IDictionary<TKey, TValue>
. Letztendlich implementiert es IEnumerable<T>
zweimal mit verschiedenen Typen für T
. Ich habe die primäre aufzählbare Schnittstelle implizit und die andere explizit implementiert. So etwas wie dieser (Pseudo-Code):
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>
}
Jetzt mag ich es die gleiche Sache in LINQ zu tun, aber es schleudert:
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();
}
Wenn ich die Hash-Tabelle foreach
, es as expected die primären enumerable nimmt Compiler-Fehler bei mir, weil er nicht weiß, welche Schnittstelle für die Erweiterungsmethoden zur Auswahl:
var xs1 = from x in hashtable // <-- 1
select x;
var xs2 = hashtable.Select(x => x); // <-- 2
Fehler 1: Eine Implementierung des Abfragemusters für den Quelltyp 'HashTable' konnte nicht gefunden werden. 'Auswählen' nicht gefunden. Erwägen Sie explizit, den Typ der Bereichsvariablen 'x' anzugeben.
Fehler 2: 'HashTable' enthält keine Definition für 'Select' und keine Erweiterungsmethode 'Select', die ein erstes Argument des Typs 'HashTable' akzeptiert (fehlt eine using-Direktive oder eine Assembly-Referenz?)
Vielleicht gibt es einen Interface- oder Vererbungstrick, von dem ich nichts weiß?
Für diejenigen, die hier gestellt wird, lautet der vollständige Baum von Schnittstellen:
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>
Jetzt können Sie sehen, warum ich nicht KeyValuePair<TKey, TValue>
und IAssociation<TKey, TValue>
das gleiche machen könnte.
Haben Sie versucht, die [generischen Argumente] ('http://msdn.microsoft.com/de-de/library/bb548891.aspx) von' Select' manuell einzugeben? Hört sich an, als hätte es Schwierigkeiten, sie zu deuten. Insbesondere müssen Sie 'TSource' manuell angeben, aber sobald Sie einen tun, müssen Sie beides tun, denke ich. Leider verhindert dies, dass Sie anonyme Typen ohne lästige Problemumgehungen zurückgeben können. –
Können Sie den Rest der Vererbung/Schnittstellen für 'HashTable'? –
Nun, es sagt Ihnen, was zu tun ist, zumindest in Bezug auf den ersten Fehler. Sie müssen explizit sagen, welcher Typ 'x' ist: von IAssociation x in Hashtabelle wählen Sie x; –
Stonehead