Collection Adapter - collection<Foo> ==> collection<Foo.Member> ?
-
Gibt es irgendeinen trick (oder eine Bibliothek :D) mit der man verschiedene Collection Interfaces aufeinander abbilden kann?
Der häufigste Fall ist: ich habe ein IEnumerable<X> und brauche ein IEnumerable<X.Member>- bzw. das gleiche für eine ICollection. Wäre natürlich auch allgemein IEnumerable<X> -> IEnumerable<Y> über ein delegate (X) : Y nett.
Gibt's dafür was?
Wenn ich das selbst mit Generics versuche, wird das ein elendiglicher und langatmiger "template"-Wust.
-
Och, soviel "generic"-Wust ist das garnicht
public sealed class FilterEnumerator<SourceT, TargetT> { public delegate TargetT Handler(SourceT obj); public static IEnumerable<TargetT> Enumerator(IEnumerable<SourceT> source, Handler handler) { foreach (SourceT obj in source) { yield return handler(obj); } } } struct Data { public int X; } class Program { static void Main(string[] args) { Data[] list = new Data[] { new Data(), new Data(), new Data() }; foreach (int x in FilterEnumerator<Data, int>.Enumerator(list, delegate(Data obj) { return obj.X; })) { System.Diagnostics.Debug.Print("Wert: " + x.ToString()); } } }
Ob das jetzt einfacher ist als einfach über list zu iterieren und auf obj.x direkt zuzugreifen (oder obj.x als lokale Variable im Schleifenkörper zur Verfügung zu stellen), sei mal dahingestellt
EDIT: Geringfügige Optimierung
-
Sieht bei mir so ähnlich aus
Wird noch ein bißchen mehr, da System.Collections.IEnumerable und System.Collections.IEnumerable<T> haben nix miteinander zu tun - also hat man 4 Varianten...
Hätte ja sein können, daß es da noch einen Trick gibt.
-
peterchen schrieb:
Wird noch ein bißchen mehr, da System.Collections.IEnumerable und System.Collections.IEnumerable<T> haben nix miteinander zu tun
Laut MSDN2 erbt IEnumerable<T> von IEnumerable, also muss ein Generic-Enumerable automatisch ein Nongeneric-Enumerable implementieren.
-
Stimmt, ja! damit könnte IEnumerable aug IEnumerable<object> zurückfallen.
Du hast mich aber noch auf eine Idee gebracht:
class Enumerator<TDst> { public static IEnumerable<TDst> From<TSrc>(IEnumerable<TSrc> src, Mapper<TSrc, TDst> mapper) { ... } public static IEnumerable<TDst> From(System.Collections.IEnumerable src, Mapper<object, TDst> mapper) { ... }
Damit wird der caller-syntax ein bißchen hübscher, da C# den TSrc-typen automatisch ableiten kann:
Data[] list = new Data[] { new Data(), new Data(), new Data() }; foreach(int x in Enumerator<int>.From(list, delegate(Data obj) { return obj.x: });
danke
edit - unsinn ausgebaut...