434 Stimmen

Reflektierende Parameternamen: Missbrauch von C#-Lambda-Ausdrücken oder brillante Syntax?

Ich betrachte die MvcContrib Grid-Komponente und ich bin fasziniert und gleichzeitig abgestoßen von einem syntaktischen Trick, der in der Gittersyntax :

.Attributes(style => "width:100%")

Die obige Syntax setzt das style-Attribut des generierten HTML auf width:100% . Wenn Sie genau hinschauen, ist "Stil" nirgends angegeben. Er wird abgeleitet aus dem Name des Parameters im Ausdruck! Ich musste nachforschen und fand heraus, wo die "Magie" passiert:

Hash(params Func<object, TValue>[] hash)
{
    foreach (var func in hash)
    {
        Add(func.Method.GetParameters()[0].Name, func(null));
    }
}

Der Code verwendet also in der Tat den formalen Namen der Parameter zur Kompilierungszeit, um das Wörterbuch der Attribut-Name-Wert-Paare zu erstellen. Das daraus resultierende Syntaxkonstrukt ist in der Tat sehr ausdrucksstark, aber gleichzeitig auch sehr gefährlich.

Die allgemeine Verwendung von Lambda-Ausdrücken ermöglicht die Ersetzung der Namen ohne Nebenwirkung verwendet werden. Ich sehe ein Beispiel in einem Buch, das sagt collection.ForEach(book => Fire.Burn(book)) Ich weiß, dass ich in meinen Code schreiben kann collection.ForEach(log => Fire.Burn(log)) y es bedeutet dasselbe . Aber mit der MvcContrib Grid-Syntax finde ich plötzlich Code, der aktiv nach den Namen sucht und Entscheidungen trifft, die ich für meine Variablen wähle!

Also ist dies gängige Praxis mit der C# 3.5/4.0-Gemeinschaft und die Lambda-Ausdrücke Liebhaber? Oder handelt es sich um einen abtrünnigen Außenseiter, über den ich mir keine Sorgen machen sollte?

10 Stimmen

+1 für die Einführung der Hash-Rakete in C#

2 Stimmen

Foreach (var func in hash) ändern in: Array.ForEarch(hash, func => Add(func.Method.GetParameters()[0].Name, func(null)));

34 Stimmen

Ich würde behaupten, dass dies offensichtlich ist, solange man bereit ist, die Absicht des Codes zu betrachten und nicht nur die Syntax zu analysieren. Wenn Sie guten Code lesen, sollten Sie das ohnehin tun. Die Syntax ist nur ein Vehikel für die Intention, und ich würde behaupten, dass dies ein Code ist, der die Intention offenbart.

6voto

Chris R. Timmons Punkte 2157

Der Code ist sehr clever, aber er verursacht möglicherweise mehr Probleme als er löst.

Wie Sie dargelegt haben, besteht nun eine obskure Abhängigkeit zwischen dem Parameternamen (style) und einem HTML-Attribut. Zur Kompilierzeit findet keine Überprüfung statt. Wenn der Parametername falsch eingegeben wird, hat die Seite wahrscheinlich keine Laufzeit-Fehlermeldung, sondern einen viel schwieriger zu findenden Logikfehler (kein Fehler, aber falsches Verhalten).

Eine bessere Lösung wäre ein Datenelement, das zur Kompilierzeit überprüft werden kann. Also stattdessen:

.Attributes(style => "width:100%");

Code mit einer Style-Eigenschaft könnte vom Compiler überprüft werden:

.Attributes.Style = "width:100%";

oder sogar:

.Attributes.Style.Width.Percent = 100;

Das ist mehr Arbeit für die Autoren des Codes, aber dieser Ansatz nutzt die Vorteile der starken Typüberprüfungsfähigkeit von C#, die dazu beiträgt, dass Fehler gar nicht erst in den Code gelangen.

3 Stimmen

Ich schätze die Kompilierzeitüberprüfung, aber ich denke, das ist eine Frage der Meinung. Vielleicht etwas wie new Attributes() { Style: "width:100%" } würde mehr Leute überzeugen, da es knapper ist. Dennoch, alles zu implementieren, was HTML erlaubt, ist eine riesige Aufgabe, und ich kann es niemandem verdenken, wenn er einfach Strings/Lambdas/anonyme Klassen verwendet.

5voto

Horacio N. Hdez. Punkte 641

In der Tat scheint es wie Ruby =), zumindest für mich die Verwendung einer statischen Ressource für eine spätere dynamische "Lookup" passt nicht für api Design Überlegungen, hoffe, dass dieser clevere Trick ist optional in diesem api.

Wir könnten von IDictionary erben (oder auch nicht) und einen Indexer bereitstellen, der sich wie ein PHP-Array verhält, wenn Sie keinen Schlüssel hinzufügen müssen, um einen Wert festzulegen. Es wird eine gültige Verwendung von .net Semantik nicht nur c# sein, und noch brauchen Dokumentation.

Ich hoffe, das hilft

4voto

madaboutcode Punkte 2117

IMHO ist das eine coole Art, das zu tun. Wir alle lieben die Tatsache, dass die Benennung einer Klasse Controller macht es ein Controller in MVC richtig? Es gibt also Fälle, in denen die Benennung eine Rolle spielt.

Auch die Absicht ist hier sehr klar. Es ist sehr leicht zu verstehen, dass .Attribute( book => "something") führt zu book="something" y .Attribute( log => "something") führt zu log="something"

Ich denke, es sollte kein Problem sein, wenn man es wie einen Kongress behandelt. Ich bin der Meinung, dass alles, was dazu führt, dass man weniger Code schreiben muss und die Absicht deutlich macht, eine gute Sache ist.

4 Stimmen

Der Name einer Klasse Controller wird nichts bringen, wenn Sie nicht auch von Controller erben...

4voto

mfeingold Punkte 6996

Meiner Meinung nach ist das ein Missbrauch der Lambdas.

Was die syntaktische Brillanz betrifft, so finde ich style=>"width:100%" einfach verwirrend. Vor allem wegen der => anstelle von =

3voto

Craig Trader Punkte 15283

Wenn die Namen der Methoden (func) gut gewählt sind, ist dies eine hervorragende Möglichkeit, um Wartungsprobleme zu vermeiden (z. B. wenn Sie eine neue func hinzufügen, aber vergessen haben, sie in die Liste der Funktionsparameter-Zuordnung aufzunehmen). Natürlich müssen Sie dies ausführlich dokumentieren, und Sie sollten die Dokumentation für die Parameter besser automatisch aus der Dokumentation für die Funktionen in dieser Klasse generieren...

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X