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...


Log in to reply