Beste Antwort
Syntaktischer Zucker oder Syntaxzucker ist eine visuell oder logisch ansprechende „Verknüpfung“, die von der Sprache bereitgestellt wird Reduziert die Menge an Code, die in einer häufigen Situation geschrieben werden muss.
Wenn Sie beispielsweise eine Variable auf einen Wert setzen, der von einer Bedingung abhängt, können Sie dies in einer einfacheren Sprache mit weniger „Zucker“ tun dies:
int a;
if(SomeFunction() == 2)
a = 4;
else
a = 9;
Dies ist ein bisschen viel für eine so einfache Operation; In einfacheren Sprachen haben Entwickler häufig eine „Inline If“ -Funktion erstellt, um diese Logik in etwas Prägnanteres zu verpacken:
public T Iif
{
if(condition) return ifTrue;
return ifFalse;
}
...
//usage
int a = Iif(SomeFunction() == 2, 4, 9);
Dort ist die tatsächliche Verwendung jetzt viel präziser. Viele moderne Sprachen, einschließlich C #, integrieren eine solche Operation direkt in die Sprachspezifikation in Form des „ternären bedingten Operators“:
int a = SomeFunction() == 2 ? 4 : 9;
Dieser Operator ist ein von der Sprache bereitgestellter „Syntaxzucker“ für eine bedingte Operation.
Ein häufiger Unterfall dieser bedingten Variableneinstellung ist nun, dass unsere erste Wahl für ein Mittel zur Erzeugung eines Werts ist Um die Variable als null auszuwerten, sollten wir ein alternatives Mittel verwenden. Zum Beispiel:
MyClass theClass = GetMyClass();
if(theClass == null)
theClass = FailSafeMyClassGetter();
Nicht schlecht, aber wir können das verbessern:
MyClass theClass = GetMyClass() ?? FailSafeMyClassGetter();
Das „??“ Der Operator ist als „Null-Koaleszenz-Operator“ bekannt und erzeugt im Grunde genommen den ersten von links nach rechts gelesenen Wert, der nicht null ist.
Ein weiteres C #, das kürzlich erhalten wurde, war die „Auto-Eigenschaft“. Kurz gesagt, C # hat sogenannte „Eigenschaften“; Paare von Codeblöcken, die ein „Datenelement“ eines Objekts darstellen, die eine komplexere Validierungs- oder Berechnungslogik ausführen können als ein einfaches Feld, auf die jedoch zugegriffen werden kann, als ob das Element ein Feld wäre, anstatt GetX () und SetX zu verwenden () Methodenaufrufe, so dass es einfach ist, im Code zu unterscheiden, wenn Sie auf Daten zugreifen oder Operationen ausführen. Aus Konsistenz- und Wartungsgründen empfiehlt es sich in C #, bei der Implementierung öffentlich sichtbarer Datenelemente Eigenschaften anstelle von Feldern zu verwenden . Neun von zehn Fällen „umschließt“ die Eigenschaft jedoch nur eine private Feldvariable. Nach bewährten Methoden sieht die Implementierung der Eigenschaft für einen einfachen Datenwert möglicherweise folgendermaßen aus:
private int \_myIntProperty;
public int MyIntProperty
{
get
{
return \_myIntProperty;
}
set
{
\_myIntProperty = value;
}
}
Hässlich, sehr repetitiv und viel mehr Codezeilen als wir wirklich brauchen. Es war in der Vergangenheit verlockend, darauf zu verzichten Best Practice und verwenden Sie in diesen einfachen Fällen nur ein Feld. Um diese Versuchung und die nachteiligen Auswirkungen auf die Codebasis zu verringern, wenn Sie später entschieden haben, dass Sie wirklich eine Eigenschaft benötigen, haben die Designer von C # etwas Syntaxzucker in C # 3.0 aufgenommen Spezifikation:
public int MyIntProperty { get; set; }
Diese Eigenschaftsdeklaration wird als dieselbe wie die obige Deklaration behandelt, aber es ist viel schneller und einfacher, eine zu schreiben Klasse voll davon, als es auf die alte Art zu tun, und es ist auch viel einfacher zu pflegen.
Dies sind nur einige Beispiele für „Syntaxzucker“, die in C # verfügbar sind. Andere umfassen:
* Inferenz des Variablentyps – var someInt = 5;
– Der Compiler kann den Typ einer deklarierten lokalen Variablen aus der anfänglichen Zuweisung bestimmen, sodass Sie keine haben um es explizit anzugeben (und es dann zu ändern, wenn sich der Typ ändert, den Sie benötigen).
* yield return
– Viele .NET-Programme umfassen Sammlungen von Objekten und Es war früher ein ziemlich komplizierter Prozess, die IEnumerable
-Schnittstelle zu implementieren, die verschiedene integrierte Schleifen wie foreach
, um zu funktionieren, und erfordert eine ganze zweite Klasse, die IEnumerator
implementiert, um die Iteration durch die Sammlung zu handhaben. indem die Iteratorlogik selbst in der GetEnumerator () -Methode der Sammlung definiert werden kann.
* async
/ await
– In ähnlicher Weise müssen immer mehr Programmieraufgaben „asynchron“ ausgeführt werden, indem die Arbeiten Sie an einem anderen „Thread“ der Anwendung, sodass die Arbeit des Programms auf mehrere Prozessoren im modernen PC aufgeteilt werden kann, während die Benutzeroberfläche der Anwendung weiterhin auf Anforderungen des Betriebssystems reagiert, die Benutzeroberfläche neu zu zeichnen und auszuführen andere visuelle Aufgaben. Das Konzept des Threading ist nicht schwer zu verstehen, aber bis C # 4.0 war es im Wesentlichen erforderlich, Ihre Methode in zwei Teile zu teilen. Eine Methode startet die asynchrone Operation, eine zweite wird aufgerufen, wenn der Hintergrundthread die Arbeit beendet hat. Nicht mehr; Mit diesen beiden neuen Schlüsselwörtern kann eine Funktion für asynchrone Arbeit sehr synchron definiert werden, während der Compiler beim Erstellen des Codes die Methoden hinter den Kulissen aufteilt.
Antwort
Es gibt keine formale Definition von syntaktischem Zucker, dies ist ein nebulöser Begriff.
Syntaktischer Zucker in seiner am meisten akzeptierten Definition ist eine zusätzliche Syntax, die vom Compiler jedoch sofort in eine primitivere und umständlichere Form übersetzt wird ermöglicht dem Programmierer eine „süßere“ Erfahrung beim Ausdrücken bestimmter allgemeiner Anweisungen.
Das Problem bei dieser Definition ist, dass die „zusätzliche“ Syntax keine sehr aussagekräftige Beschreibung ist. In bestimmten Fällen ist es ziemlich klar, dass wir syntaktischen Zucker haben, zum Beispiel definiert der Haskell-Sprachbericht bestimmte syntaktische Elemente (Do-Blöcke und Listenverständnisse) explizit durch ihre Übersetzung in eine einfachere Syntax. Dies ist ein ziemlich eindeutiger Fall von syntaktischem Zucker. Sie existieren nur, um das Schreiben eines Programms zu erleichtern, nicht in einem tiefgreifenden Sinne bei der Compilerübersetzung des Programms in einen symbolischen Baum.
In anderen Fällen Es ist viel weniger klar, weil die Sprache sich nicht um diese Art der Formalisierung kümmert. Zum Beispiel werden Dekorateure in Python oft dadurch beschrieben, wie Sie den entsprechenden Code ohne sie schreiben würden, aber soweit ich weiß, wird nie explizit gesagt: „Sie sollten Dekorateure nicht direkt in Ihre Zwischendarstellung kompilieren, sondern vorher auf diese Weise übersetzen. “ Einige Implementierungen von Python entscheiden sich möglicherweise dafür, andere haben möglicherweise Dekoratoren als Merkmal ihrer Zwischendarstellung hinzugefügt.