Beste antwoord
Syntactische suiker, of syntaxis suiker, is een visueel of logisch aantrekkelijke snelkoppeling van de taal, die vermindert de hoeveelheid code die in een veel voorkomende situatie moet worden geschreven.
Als u bijvoorbeeld een variabele instelt op een waarde die afhankelijk is van een voorwaarde, kunt u in een eenvoudigere taal met minder “suiker” doen dit:
int a;
if(SomeFunction() == 2)
a = 4;
else
a = 9;
Dit is een beetje veel voor zon eenvoudige handeling; in eenvoudiger talen creëerden ontwikkelaars vaak een “Inline If” -functie om deze logica in iets beknopter te verpakken:
public T Iif
{
if(condition) return ifTrue;
return ifFalse;
}
...
//usage
int a = Iif(SomeFunction() == 2, 4, 9);
Nu is het daadwerkelijke gebruik veel beknopter. Veel moderne talen, waaronder C #, nemen een bewerking als deze rechtstreeks op in de taalspecificatie in de vorm van de “ternaire voorwaardelijke operator”:
int a = SomeFunction() == 2 ? 4 : 9;
Deze operator is een door de taal geleverde “syntaxis suiker” voor een voorwaardelijke bewerking.
Nu, een veelvoorkomend subgeval van deze voorwaardelijke variabele-instelling is dat als onze eerste keuze voor een middel om een waarde te produceren om de variabele in te stellen als null, moeten we een alternatief middel gebruiken. Bijvoorbeeld:
MyClass theClass = GetMyClass();
if(theClass == null)
theClass = FailSafeMyClassGetter();
Niet slecht, maar we kunnen dit verbeteren:
MyClass theClass = GetMyClass() ?? FailSafeMyClassGetter();
De “??” operator staat bekend als de “null-coalescerende operator” en het produceert in feite de eerste waarde zoals gelezen van links naar rechts die niet null is.
Een andere C # die onlangs werd gekregen was de “auto-eigenschap”. Kort gezegd heeft C # zogenaamde “eigenschappen”; paren codeblokken die een gegevenslid van een object vertegenwoordigen, die complexere validatie- of berekeningslogica kunnen uitvoeren dan een eenvoudig veld zou kunnen, maar die toegankelijk zijn alsof het lid een veld is in plaats van GetX () en SetX te gebruiken () methodeaanroepen, zodat het gemakkelijk wordt om onderscheid te maken in code wanneer u “opnieuw toegang krijgt tot gegevens versus uitvoeren van bewerkingen. Het is een best practice in C #, om redenen van consistentie en onderhoud, om eigenschappen te gebruiken in plaats van velden bij het implementeren van openbaar zichtbare gegevensleden . Negen van de tien keer is de eigenschap echter slechts een privéveldvariabele “omhullend”, en volgens de beste praktijken kan de implementatie van de eigenschap voor een eenvoudige gegevenswaarde er als volgt uitzien:
private int \_myIntProperty;
public int MyIntProperty
{
get
{
return \_myIntProperty;
}
set
{
\_myIntProperty = value;
}
}
Een beetje lelijk, erg repetitief en veel meer regels code dan we echt nodig hebben. Het was in het verleden verleidelijk om ervan af te zien best practice en gebruik gewoon een veld in deze eenvoudige gevallen, dus om die verleiding te verminderen en het schadelijke effect dat het op de codebase kan hebben als je later besloot dat je echt een eigenschap nodig had, hebben de ontwerpers van C # wat syntaxis in de C # 3.0 opgenomen specificatie:
public int MyIntProperty { get; set; }
Deze eigenschapdeclaratie wordt behandeld als hetzelfde als de bovenstaande declaratie, maar het is veel sneller en gemakkelijker om een klasse vol met deze dan om het op de oude manier te doen, en het is ook veel gemakkelijker te onderhouden.
Dit zijn slechts een paar voorbeelden van “syntax sugar” beschikbaar in C #. Andere omvatten:
* Variabele type inferentie – var someInt = 5;
– De compiler kan het type van een gedeclareerde lokale variabele bepalen aan de hand van de initiële toewijzing, dus je hoeft niet om het expliciet te specificeren (en verander het dan als het type dat je nodig hebt veranderingen).
* yield return
– Veel .NET-programmering omvat verzamelingen van objecten, en repetitieve taken uitvoeren op elk element van hetzelfde. Vroeger was het een behoorlijk ingewikkeld proces om de IEnumerable
-interface te implementeren die verschillende ingebouwde lussen toestaat, zoals foreach
om te functioneren, waarvoor een volledige tweede klasse nodig was die IEnumerator
implementeerde om iteratie door de verzameling af te handelen. Het yield return
sleutelwoord vereenvoudigde dat dramatisch, door de iteratorlogica zelf te laten definiëren binnen de eigen GetEnumerator () – methode van de collectie.
* async
/ await
– Evenzo moeten steeds meer programmeertaken “asynchroon” worden uitgevoerd door de werken aan een andere thread van de applicatie, zodat het werk van het programma kan worden verdeeld over de meerdere processors op de moderne pc, terwijl de gebruikersinterface van de applicatie reageert op verzoeken van het besturingssysteem om de gebruikersinterface opnieuw te tekenen en uit te voeren andere visuele taken. Het concept van threading is niet moeilijk te begrijpen, maar tot C # 4.0 moest je in wezen je methode in tweeën splitsen; de ene methode start de asynchrone bewerking, vervolgens wordt een tweede aangeroepen wanneer de achtergrondthread het werk heeft voltooid. Niet meer; Met deze twee nieuwe sleutelwoorden kan een functie die asynchroon werk doet, op een zeer synchrone manier worden gedefinieerd, terwijl de compiler achter de schermen de methode splitst bij het bouwen van de code.
Antwoord
Er is geen formele definitie van syntactische suiker, dit is een vaag begrip.
Syntactische suiker in zijn meest geaccepteerde definitie is een extra syntaxis die onmiddellijk wordt vertaald naar een meer primitieve en omslachtige vorm door de compiler, maar geeft de programmeur een “zoetere” ervaring bij het uitdrukken van bepaalde algemene instructies.
Het probleem met deze definitie is dat de “extra” syntaxis geen erg zinvolle beschrijving is. In bepaalde gevallen is het vrij duidelijk dat we syntactische suiker hebben, bijvoorbeeld het Haskell-taalrapport definieert expliciet bepaalde syntactische elementen (do-blocks en lijstbegrip) door hun vertaling in een eenvoudigere syntaxis. Dit is een vrij duidelijk geval van syntactische suiker, ze bestaan alleen om het schrijven van een programma te vergemakkelijken, niet in enige diepere zin bij de compilervertaling van het programma naar een symbolische boom.
In andere gevallen, het is veel minder duidelijk omdat de taal zich niet bezighoudt met dit soort formalisatie, bijvoorbeeld decorateurs in Python worden vaak beschreven door hoe je de equivalente code zou schrijven zonder hen, maar voor zover ik weet wordt er nooit expliciet gezegd: “jij moet decorateurs niet rechtstreeks in uw tussenvoorstelling compileren, maar ze eerder op deze manier vertalen ”. Sommige implementaties van Python kiezen ervoor om precies dat te doen, maar andere hebben mogelijk decorateurs toegevoegd als een kenmerk van hun tussenliggende representatie.