2013-07-18 16 views
5

Ich meine diese Frage nicht zu subjektiv.Wird LINQ für ein einzelnes Objekt als schlechte Methode betrachtet?

Ich googelte das für einige Zeit, aber bekam keine spezifischen Antworten auf dieses Problem. Die Sache ist, ich glaube, ich bin etwas süchtig nach LINQ. Ich habe LINQ bereits verwendet, um in Listen unter anderem Linq zu SQL, Xml usw. abzufragen. Aber dann ist mir etwas aufgefallen: "Was wäre, wenn ich ein einzelnes Objekt abfragen würde?" Also tat ich es. Es mag falsch erscheinen, als würde man versuchen, eine Fliege mit einem Granatwerfer zu töten. Obwohl wir uns alle einig sind, wäre es künstlerisch angenehm zu sehen.


Ich halte es für sehr lesbar, ich glaube nicht, dass es keine Performance-Probleme ist dies in Bezug auf, aber lassen Sie mich Ihnen ein Beispiel.

In einer Webanwendung muss ich eine Einstellung aus meiner Konfigurationsdatei (web.config) abrufen. Dies sollte jedoch einen Standardwert haben, wenn der Schlüssel nicht vorhanden ist. Außerdem ist der Wert, den ich benötige, eine Dezimalzahl, keine Zeichenkette. Dies ist die Standardrückgabe von ConfigurationManager.AppSettings["myKey"]. Außerdem sollte meine Nummer nicht mehr als 10 sein und es sollte nicht negativ sein. Ich weiß, dass ich das schreiben könnte:

string cfg = ConfigurationManager.AppSettings["myKey"]; 
decimal bla; 
if (!decimal.TryParse(cfg,out bla)) 
{ 
    bla = 0; // 0 is the default value 
} 
else 
{ 
    if (bla<0 || bla>10) 
    { 
     bla = 0; 
    } 
} 

Das ist nicht kompliziert, nicht gewunden, und einfach zu lesen. Dies ist jedoch, wie ich es getan mag:

// initialize it so the compiler doesn't complain when you select it after 
decimal awesome = 0; 
// use Enumerable.Repeat to grab a "singleton" IEnumerable<string> 
// which is feed with the value got from app settings 
awesome = Enumerable.Repeat(ConfigurationManager.AppSettings["myKey"], 1) 
    // Is it parseable? grab it 
    .Where(value => decimal.TryParse(value, out awesome)) 
    // This is a little trick: select the own variable since it has been assigned by TryParse 
    // Also, from now on I'm working with an IEnumerable<decimal> 
    .Select(value => awesome) 
    // Check the other constraints 
    .Where(number => number >= 0 && number <= 10) 
    // If the previous "Where"s weren't matched, the IEnumerable is empty, so get the default value 
    .DefaultIfEmpty(0) 
    // Return the value from the IEnumerable 
    .Single(); 

Ohne die Kommentare, sieht es so aus:

decimal awesome = 0; 
awesome = Enumerable.Repeat(ConfigurationManager.AppSettings["myKey"], 1) 
    .Where(value => decimal.TryParse(value, out awesome)) 
    .Select(value => awesome) 
    .Where(number => number >= 0 && number <= 10) 
    .DefaultIfEmpty(0) 
    .Single(); 

weiß ich nicht, ob ich der einzige hier bin, aber ich glaube, die zweite Methode ist viel "organischer" als die erste. Es ist nicht leicht debuggbar, wegen LINQ, aber es ist ziemlich versagen, denke ich. Zumindest diesen habe ich geschrieben. Wie auch immer, wenn Sie debuggen müssen, könnten Sie einfach geschweifte Klammern hinzufügen und Anweisungen innerhalb der linq Methoden zurückgeben und glücklich darüber sein.

Ich mache das schon seit einer Weile, und es fühlt sich viel natürlicher an als Dinge zu tun "Linie pro Linie, Schritt für Schritt". Außerdem habe ich den Standardwert nur einmal angegeben. Und es ist in einer Zeile geschrieben, die DefaultIfEmpty sagt, also ist es ziemlich einfach.

Ein weiteres Plus, ich mache es definitiv nicht, wenn ich bemerke, dass die Abfrage viel größer sein wird als die, die ich dort geschrieben habe. Stattdessen zerbreche ich in kleinere Stücke von linq Ruhm, so dass es leichter zu verstehen und zu debuggen ist.

Ich finde es einfacher, eine Variablenzuweisung zu sehen und automatisch zu denken: das war, was Sie tun mussten, um diesen Wert einzustellen, anstatt ifs, elnes, Schalter und usw. zu betrachten und zu versuchen herauszufinden, ob Sie sind Teil der Formel oder nicht.

Und es verhindert, dass Entwickler unerwünschte Nebenwirkungen an falschen Orten schreiben, denke ich.

Aber am Ende, sagen einige könnte es sehr hackish oder zu arkanen aussieht.

So komme ich mit der Frage auf der Hand:

Ist LINQ gegen ein einzelnes Objekt mit einer schlechten Praxis in Betracht gezogen?

+0

Ich denke, das könnte ein bisschen subjektiv sein. –

+0

Wenn ich diesen Code überprüfen müsste, würde ich mich selbst töten. Bitte nehmen Sie Rücksicht auf Ihre Mitarbeiter. – fcuesta

+0

@fcuesta Haha Ich dachte es, und ich hatte etwas Angst davor. Vielleicht muss ich diese "künstlerische Programmierung", die ich in letzter Zeit erlebt habe, loslassen. Nicht immer muss alles ein One-Liner sein. –

Antwort

7

Ich sage ja, aber es ist wirklich zu bevorzugen. Es hat definitiv Nachteile, aber das überlasse ich Ihnen. Ihr ursprünglicher Code kann jedoch viel einfacher werden.

string cfg = ConfigurationManager.AppSettings["myKey"]; 
decimal bla; 
if (!decimal.TryParse(cfg,out bla) || bla < 0 || bla > 10) 
    bla = 0; // 0 is the default value 

Das funktioniert, weil die „Kurzschluss“ Auswertung, was bedeutet, dass das Programm andere Bedingungen überprüft wird gestoppt, sobald die erste wahre Bedingung gefunden wird.

+0

Sie haben Recht, ich habe abgestimmt. Könnten Sie einige der "Nachteile" des Schreibens von Code wie diesem nennen, neben einigen Kollegen, die es als "schwierig" oder "unnötig komplex" empfinden? Vielen Dank. –

+0

Nun, zum einen müssen Sie ein Objekt für die Zustandsmaschine für den Iterator erstellen. Als nächstes nimmst du einen Nebeneffekt mit der Auswahl der "tollen" Variable in Anspruch. Wenn jemand versagt und Sie 2 Iterationen bekommen, dann wird das problematisch. Wenn also jemand nicht einmal versteht, wie "out" funktioniert, werden sie durch diese nachfolgende Auswahl verwirrt. Drittens brauchen Sie viele Delegierte mit Schließungen, wenn Sie sie nicht brauchen. Viertens haben Sie viel mehr Methodenaufrufe, als Sie jemals brauchen würden. –

+0

Ich sehe, Sie haben einen Punkt. Ich stelle das als Antwort dar, weil Sie es klar begründet haben, obwohl ich noch ein wenig mehr ausgraben werde, um zu sehen, ob ich den Code wirklich "überkomplezi" oder einfach auf ein anderes (aber nicht unbedingt schlechtes) Paradigma umschalte. Vielen Dank. –

Verwandte Themen