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.

43voto

Sam Saffron Punkte 124121

Dies ist Schrecklich auf mehr als einer Ebene. Und nein, das ist nicht wie Ruby. Es ist ein Missbrauch von C# und .NET.

Es gibt viele Vorschläge, wie man dies auf einfachere Weise erreichen kann: Tupel, anonyme Typen, eine fließende Schnittstelle und so weiter.

Was ihn so schlecht macht, ist, dass er für sein eigenes Wohlbefinden viel zu ausgefallen ist:

  • Was passiert, wenn Sie diese Funktion von Visual Basic aus aufrufen müssen?

    .Attributes(Function(style) "width:100%")

  • Es ist völlig kontraintuitiv, und intellisense wird wenig Hilfe bieten, um herauszufinden, wie man etwas einfügt.

  • Das ist unnötig ineffizient.

  • Niemand wird eine Ahnung haben, wie er zu warten ist.

  • Was ist der Typ des Arguments, das in die Attribute eingeht? Func<object,string> ? Inwiefern ist diese Absicht aufschlussreich? Was wird Ihre Intellisense-Dokumentation sagen: "Bitte alle Werte des Objekts ignorieren"?

Ich denke, Sie haben völlig Recht, wenn Sie diese Gefühle des Abscheus haben.

4 Stimmen

Ich würde sagen, es ist völlig intuitiv :)

4 Stimmen

Sie sagen, es ist nicht wie Ruby. Aber es ist der Ruby-Syntax für die Angabe der Schlüssel und Werte einer Hashtabelle verdammt ähnlich.

3 Stimmen

Code, der bei der Alpha-Konvertierung nicht funktioniert! Juhu!

38voto

Blindy Punkte 59463

Ich gehöre zum Lager der "Syntax-Genialität". Wenn sie es klar dokumentieren und es so verdammt cool aussieht, gibt es imo fast kein Problem damit!

11 Stimmen

Amen, Bruder. Amen (2. Amen erforderlich, um die Mindestlänge für Kommentare einzuhalten :)

0 Stimmen

Ihr Kommentar allein war schon mehr als nötig. Aber man kann ja nicht nur einmal Amen sagen und dann seinen Kommentar einfügen :D

37voto

Arnis Lapsa Punkte 42566

Beides. Es ist der Missbrauch von Lambda-Ausdrücken ET syntaktische Brillanz.

17 Stimmen

Es ist also ein genialer syntaktischer Missbrauch von Lambda-Ausdrücken? Ich denke, ich stimme zu :)

22voto

Elisha Punkte 22640

Ich habe diese Art der Verwendung nur selten erlebt. Ich denke, es ist "unangemessen" :)

Dies ist keine übliche Art der Verwendung, sie widerspricht den allgemeinen Konventionen. Diese Art der Syntax hat natürlich Vor- und Nachteile:

Nachteile

  • Der Code ist nicht intuitiv (die üblichen Konventionen sind anders)
  • Es neigt dazu, anfällig zu sein (Umbenennung von Parametern macht die Funktionalität kaputt).
  • Es ist ein wenig schwieriger zu testen (faking die API wird die Verwendung von Reflexion in Tests erfordern).
  • Wenn der Ausdruck intensiv genutzt wird, wird er langsamer sein, da der Parameter und nicht nur der Wert analysiert werden muss (Reflexionskosten).

Profis

  • Nachdem sich der Entwickler auf diese Syntax eingestellt hat, ist sie besser lesbar.

Unterm Strich - bei der Entwicklung öffentlicher APIs hätte ich einen expliziteren Weg gewählt.

2 Stimmen

@Elisha - Ihre Vor- und Nachteile sind vertauscht. Zumindest hoffe ich, dass Sie nicht sagen, dass es ein Pro ist, wenn der Code "nicht intuitiv" ist ;-)

0 Stimmen

Für diesen speziellen Fall - Lambda-Parameter Name und String-Parameter sind beide fragil. Es ist wie die Verwendung von dynamischen für Xml-Parsing - es ist angemessen, weil Sie nicht sicher über Xml sowieso sein kann.

19voto

Guffa Punkte 663241

Nein, das ist sicherlich keine gängige Praxis. Es ist kontraintuitiv, man kann sich den Code nicht einfach ansehen, um herauszufinden, was er bewirkt. Man muss wissen, wie er verwendet wird, um zu verstehen, wie er verwendet wird.

Anstatt Attribute über ein Array von Delegierten zu liefern, wäre eine Verkettung von Methoden übersichtlicher und würde besser funktionieren:

.Attribute("style", "width:100%;").Attribute("class", "test")

Das ist zwar etwas aufwendiger zu tippen, aber klar und intuitiv.

6 Stimmen

Wirklich? Ich wusste genau, was dieser Codeschnipsel bedeutet, als ich ihn sah. Es ist nicht so stumpfsinnig, es sei denn, man ist sehr streng. Man könnte dasselbe Argument über das Überladen von + für die String-Verkettung anführen, und dass wir stattdessen immer eine Concat()-Methode verwenden sollten.

4 Stimmen

@Stuart: Nein, du wusstest es nicht genau, du hast nur auf der Grundlage der verwendeten Werte geraten. Jeder kann diese Vermutung anstellen, aber Vermutungen sind kein guter Weg, um Code zu verstehen.

11 Stimmen

Ich schätze, mit .Attribute("style", "width:100%") gibt mir style="width:100%" aber nach allem, was ich weiß, könnte es mir foooooo . Ich sehe den Unterschied nicht.

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