2017-08-03 2 views
2

LINQ ermöglicht die Erfassung durch ein Verfahren zu einer anderen Sammlung, dhTransform, ein Objekt zu einem anderen, LINQ-style

var x = SomeMethod().Select(t => new { ... }); 

Nun zurück zu elegant-Transformation, eine präzise Art und Weise, den Rückgabewert zu transformieren, in C# bestehen einer Methode ohne eine Zwischenvariable einzuführen? Deklarieren und den Aufruf einer Lambda scheint zu funktionieren, aber ist ziemlich hässlich:

var x = new Func<T, object>(t => { return new { ... }; })(SomeMethod()); 

Fehle ich etwas offensichtlich oder ist dies das Beste, was man heute mit C# tun?

+0

Warum würden Sie denken, dass Code hässlich ist? Das einzige, was ich tun würde, ist 'var' durch den tatsächlichen Rückgabetyp zu tauschen und den Objekttyp anzugeben (falls zutreffend), aber ansonsten halte ich das für einen akzeptablen Code. – hbulens

+0

[Tuple Dekonstruktion] (https://docs.microsoft.com/en-us/dotnet/csharp/tuples#deconstruction) ist nicht vollständig allgemein, aber in einigen Szenarien anwendbar. Im Allgemeinen sehe ich wirklich nicht, was falsch ist mit (keuchen!) Schreiben * zwei Zeilen * Code statt eins ('var x = SomeMethod(); var y = neu {x.foo, x.bar, .. .} '). Es gibt keine Steuer auf Linien oder Variablen, und es ist auch nicht so, dass irgendetwas kürzeres die Vermittler sowieso nicht unter die Decke bringt. –

+0

@ JeroenMostert stimme ich voll und ganz zu. Ich stelle diese Frage hauptsächlich aus intellektueller Neugierde. –

Antwort

1

Sie können Select von Single zu Folge von einem Elemente aus dem Ergebnis SomeMethod des Aufrufs erstellt gefolgt gelten, wie folgt:

var x = Enumerable.Repeat(SomeMethod(), 1).Select(r => new {...}).Single(); 

Wenn Sie ihm eine Menge zu tun, können Sie eine allgemeine Erweiterungsmethode für diese machen :

static class MyExtensions { 
    public static TRes Transform<TSrc,TRes>(this TSrc src, Func<TSrc,TRes> selector) { 
     return selector(src); 
    } 
} 

Jetzt wird die Syntax sehr einfach:

var res = SomeMethod().Transform(x => new { ... }); 
+0

Richtig, ich bin mir nicht sicher, es ist viel besser als ein Lambda zu deklarieren und aufzurufen :) –

+0

@ FrançoisBeaune Damit vermeiden Sie es, das Lambda zu deklarieren, d. H. 'Func <...>' bleibt außerhalb des Bildes. – dasblinkenlight

+0

Ich dachte daran, das als Antwort aufzusetzen, aber ein intermediäres Array zu konstruieren, über es zu iterieren und es dann wieder auf ein einzelnes Element zu reduzieren, ist ziemlich hässlich in seiner Ineffizienz, wenn man es konsequent anwendet). Und all das, um eine * sichtbare * Zwischenvariable zu eliminieren! –

0

Ich dachte nur, dass eine generische Erweiterung Methode, um die Lücke füllen könnte:

public static class TransformExtension 
{ 
    public static T2 Transform<T1, T2>(this T1 t1, Func<T1, T2> transform) 
    { 
     return transform(t1); 
    } 
} 

Verwendungsbeispiel:

public class A { }; 
public class B { }; 

void Foo() 
{ 
    var a = new A(); 
    var b = a.Transform(x => new B()); 
} 

glücklich zu hören, warum das ist vielleicht eine schreckliche Idee.

+1

Sie müssen 'T1' und' T2' nicht einmal auf eine Klasse beschränken (siehe meine letzte Bearbeitung). – dasblinkenlight

+0

@dasblinkenlight Oh, ich habe deine Bearbeitung nicht gesehen, ich habe diese Lösung unabhängig gefunden ... Guter Punkt über die Einschränkungen, ich werde sie entfernen. Ich werde deine Lösung akzeptieren, da es nur fair ist :) –

Verwandte Themen