Bästa svaret
Syntaktiskt socker, eller syntaxsocker, är en visuellt eller logiskt tilltalande ”genväg” som tillhandahålls av språket, vilket minskar mängden kod som måste skrivas i någon vanlig situation.
Till exempel, när du ställer in en variabel till ett värde som är beroende av ett tillstånd, på ett enklare språk med mindre ”socker” kan du göra detta:
int a;
if(SomeFunction() == 2)
a = 4;
else
a = 9;
Detta är lite för en så enkel operation; på enklare språk skapade utvecklare ofta en “Inline If” -funktion för att slå in den här logiken i något mer koncist:
public T Iif
{
if(condition) return ifTrue;
return ifFalse;
}
...
//usage
int a = Iif(SomeFunction() == 2, 4, 9);
Nu är den faktiska användningen mycket mer kortfattad. Många moderna språk inklusive C # införlivar en sådan operation direkt i språkspecifikationen i form av den ”ternära villkorliga operatören”:
int a = SomeFunction() == 2 ? 4 : 9;
Denna operatör tillhandahålls språkligt ”syntaxsocker” för en villkorlig operation.
Nu är ett vanligt underfall av denna villkorliga variabelinställning att om vårt första val för ett medel för att producera ett värde för att ställa in variabeln utvärderas som noll, bör vi använda ett alternativt medel. Till exempel:
MyClass theClass = GetMyClass();
if(theClass == null)
theClass = FailSafeMyClassGetter();
Inte dåligt, men vi kan förbättra det:
MyClass theClass = GetMyClass() ?? FailSafeMyClassGetter();
”??” operatören är känd som ”null-koalescerande operator” och den producerar i princip det första värdet som läst från vänster till höger som inte är null. Sammanfattningsvis har C # det som kallas ”egenskaper”; par kodblock som representerar en ”data-medlem” av ett objekt, som kan utföra mer komplexa validerings- eller beräkningslogik än ett enkelt fält kan, men som kan nås som om medlemmen var ett fält istället för att använda GetX () och SetX () metodanrop, så det blir lätt att skilja i kod när du får åtkomst till data kontra att utföra operationer. Det är bästa praxis i C #, för konsekvens och underhållsskäl, att använda egenskaper istället för fält när du implementerar offentligt synliga datamedlemmar . Men nio gånger av tio släpper fastigheten bara en privat fältvariabel, och enligt bästa praxis kan fastighetsimplementeringen för ett enkelt datavärde se ut:
private int \_myIntProperty;
public int MyIntProperty
{
get
{
return \_myIntProperty;
}
set
{
\_myIntProperty = value;
}
}
Typ av fula, väldigt repetitiva och mycket fler kodrader än vad vi verkligen behöver. Det var frestande tidigare att avstå bästa praxis och använd bara ett fält i dessa enkla fall, så för att minska den frestelsen och den skadliga effekten det kan ha på kodbasen om du senare bestämde att du verkligen behövde en fastighet, inkluderade C # ”s designers några syntaxsocker i C # 3.0 specifikation:
public int MyIntProperty { get; set; }
Denna egendomsdeklaration behandlas som den samma som ovanstående deklaration, men det är mycket snabbare och lättare att skriva en klass full av dessa än att göra det på gamla sätt, och det är mycket lättare att underhålla också.
Detta är bara ett par exempel på ”syntax socker” som finns i C #. Andra inkluderar:
* Inferens av variabel typ – var someInt = 5;
– Kompilatorn kan bestämma typen av en deklarerad lokal variabel från den ursprungliga tilldelningen, så att du inte har för att specifikt specificera det (och sedan ändra det om den typ du behöver ändras).
* yield return
– Mycket .NET-programmering involverar samlingar av objekt och gör repetitiva uppgifter på varje element av samma. Det brukade vara en ganska involverad process för att implementera IEnumerable
gränssnitt som tillåter olika inbyggda slingor som foreach
för att fungera, vilket kräver en hel andra klass som implementerade IEnumerator
för att hantera iterering genom samlingen. Nyckelordet yield return
dramatiskt förenklar det, genom att låta själva iteratorlogiken definieras inom samlingens egen GetEnumerator () -metod.
* async
/ await
– På samma sätt måste fler och fler programmeringsuppgifter köras ”asynkront” genom att ge arbeta till en annan ”tråd” i applikationen, så att programmets arbete kan delas mellan flera processorer i den moderna datorn, medan användargränssnittet för applikationen förblir ”lyhörd” för OS: s begäran om att rita om användargränssnittet och utföra andra visuella uppgifter. Begreppet trådning är inte svårt att förstå, men tills C # 4.0 krävdes det i huvudsak att dela din metod i två; en metod startar den asynkrona operationen, sedan kallas en sekund när bakgrundstråden har avslutat arbetet. Inte mer; dessa två nya nyckelord tillåter att en funktion som gör asynkront arbete kan definieras på ett mycket synkront sätt, medan kompilatorn gör metoduppdelningen bakom kulisserna när man bygger koden.
Svar
Det finns ingen formell definition av syntaktiskt socker, detta är ett otydligt begrepp.
Syntaktiskt socker i sin mest accepterade definition är extra syntax som omedelbart översätts till en mer primitiv och besvärlig form av kompilatorn men tillåter en ”sötare” upplevelse för programmeraren att uttrycka vissa vanliga instruktioner.
Problemet med denna definition är att ”extra” syntax inte är en mycket meningsfull beskrivning. I vissa fall är det ganska tydligt att vi har syntaktiskt socker, till exempel definierar Haskells språkrapport uttryckligen vissa syntaktiska element (do-blocks och listförståelser) genom deras översättning i en enklare syntax. Detta är ett ganska tydligt fall av syntaktiskt socker, de finns bara för att underlätta skrivandet av ett program, inte i någon djupgående mening i översättningen av programmet till ett symboliskt träd.
I andra fall, det är mycket mindre tydligt eftersom språket inte bryr sig om denna typ av formalisering, till exempel beskrivs dekoratörer i Python ofta av hur du skulle skriva motsvarande kod utan dem men så vitt jag vet sägs det aldrig uttryckligen: ”du ska inte sammanställa dekoratörer direkt i din mellanrepresentation utan snarare översätta dem på detta sätt i förväg ”. En del implementering av Python kan välja att göra just det men andra kan ha lagt till dekoratörer som en del av deras mellanrepresentation.