Cel mai bun răspuns
Zaharul sintactic sau zahărul sintaxic este o „scurtătură” atractivă din punct de vedere vizual sau logic oferită de limbă, care reduce cantitatea de cod care trebuie scris într-o situație obișnuită.
De exemplu, atunci când setați o variabilă la o valoare care depinde de o condiție, într-un limbaj mai simplu, cu mai puțin „zahăr”, ați putea face aceasta:
int a;
if(SomeFunction() == 2)
a = 4;
else
a = 9;
Acest lucru este cam mult pentru o operație atât de simplă; în limbaje mai simple, dezvoltatorii au creat adesea o funcție „Inline If” pentru a înfășura această logică în ceva mai concis:
public T Iif
{
if(condition) return ifTrue;
return ifFalse;
}
...
//usage
int a = Iif(SomeFunction() == 2, 4, 9);
Acolo, acum utilizarea efectivă este mult mai concisă. Multe limbi moderne, inclusiv C #, încorporează o astfel de operație direct în specificațiile de limbă sub forma „operatorului condițional ternar”:
int a = SomeFunction() == 2 ? 4 : 9;
Acest operator este „sintaxa zahărului” oferită de limbă pentru o operație condiționată.
Acum, un sub-caz comun al acestei setări de variabilă condiționată este că, dacă prima noastră alegere pentru un mijloc de a produce o valoare pentru a seta la variabila se evaluează ca nul, ar trebui să folosim un mijloc alternativ. De exemplu:
MyClass theClass = GetMyClass();
if(theClass == null)
theClass = FailSafeMyClassGetter();
Nu este rău, dar putem îmbunătăți acest lucru:
MyClass theClass = GetMyClass() ?? FailSafeMyClassGetter();
„??” operatorul este cunoscut sub numele de „operator de coaliție nulă” și produce practic prima valoare citită de la stânga la dreapta, care nu este nulă.
Un alt C # obținut recent a fost „proprietatea automată”. În concluzie, C # are ceea ce se numește „proprietăți”; perechi de blocuri de cod care reprezintă un „membru de date” al unui obiect, care pot efectua o validare mai complexă sau o logică de calcul decât ar putea face un câmp simplu, dar care poate fi accesată ca și cum membrul ar fi un câmp în loc să folosească GetX () și SetX () apeluri de metodă, astfel încât devine ușor de diferențiat în cod atunci când „accesați date față de efectuarea operațiunilor. Este cea mai bună practică în C #, din motive de consistență și întreținere, să utilizați proprietăți în loc de câmpuri atunci când implementați membri de date vizibili public . Cu toate acestea, de nouă ori din zece, proprietatea „doar” împachetează ”o variabilă de câmp privat și, astfel, urmând cele mai bune practici, implementarea proprietății pentru o valoare simplă a datelor ar putea arăta ca:
private int \_myIntProperty;
public int MyIntProperty
{
get
{
return \_myIntProperty;
}
set
{
\_myIntProperty = value;
}
}
Un fel de urât, foarte repetitiv și cu mult mai multe linii de cod decât avem cu adevărat nevoie. În trecut a fost tentant să renunțăm cele mai bune practici și pur și simplu folosiți un câmp în aceste cazuri simple, deci pentru a reduce acea tentație și efectul dăunător pe care îl poate avea asupra bazei de cod dacă mai târziu ați decis că într-adevăr aveți nevoie de o proprietate, designerii C # au inclus niște zahăr de sintaxă în C # 3.0 specificație:
public int MyIntProperty { get; set; }
Această declarație de proprietate este tratată ca fiind aceeași cu declarația de mai sus, dar este mult mai rapid și mai ușor să scrieți un clasă plină de acestea decât să o faci la fel ca la vechime și „este mult mai ușor de întreținut.
Acestea sunt doar câteva exemple de„ sintaxă zahăr ”disponibile în C #. Altele includ:
* inferență de tip variabil – var someInt = 5;
– Compilatorul poate determina tipul unei variabile locale declarate din atribuirea inițială, deci nu aveți să o specificați în mod explicit (și apoi să o modificați dacă se modifică tipul de care aveți nevoie).
* yield return
– O mulțime de programare .NET implică colecții de obiecte și efectuarea de sarcini repetitive pe fiecare element al acestuia. Obișnuia să fie un proces destul de implicat pentru a implementa interfața IEnumerable
care permite diverse bucle încorporate precum foreach
pentru a funcționa, necesitând o întreagă a doua clasă care a implementat IEnumerator
pentru a gestiona iterarea prin colecție. permițând ca logica iteratorului să fie definită în cadrul metodei GetEnumerator () a colecției.
* async
/ await
– În mod similar, tot mai multe activități de programare trebuie executate „asincron”, oferind lucrați la un alt „fir” al aplicației, astfel încât munca programului poate fi împărțită între multiplele procesoare din PC-ul modern, în timp ce interfața cu utilizatorul aplicației rămâne „receptivă” la solicitările OS pentru a redesena interfața de utilizare și a alte sarcini vizuale. Conceptul de threading nu este dificil de înțeles, dar până la C # 4.0 a necesitat în esență împărțirea metodei în două; o metodă pornește operațiunea asincronă, apoi se apelează oa doua când firul de fundal a terminat lucrarea. Nu mai; aceste două noi cuvinte cheie permit definirea unei funcții asincrone într-un mod foarte sincron, în timp ce compilatorul realizează divizarea metodelor din culise atunci când construiește codul.
Răspuns
Nu există o definiție formală a zahărului sintactic, aceasta este o noțiune nebuloasă.
Zaharul sintactic în definiția sa cea mai acceptată este o sintaxă suplimentară care este tradusă imediat într-o formă mai primitivă și greoaie de către compilator, dar permite o experiență „mai dulce” pentru programator în exprimarea anumitor instrucțiuni comune.
Problema cu această definiție este că sintaxa „suplimentară” nu este o descriere foarte semnificativă. În anumite cazuri, este destul de clar că avem zahăr sintactic, de exemplu, raportul lingvistic Haskell definește în mod explicit anumite elemente sintactice (blocuri de lucru și înțelegeri de listă) prin traducerea lor într-o sintaxă mai simplă. Acesta este un caz destul de clar de zahăr sintactic, acestea există doar pentru a facilita scrierea unui program, nu în nici un sens profund în traducerea compilatorului programului într-un arbore simbolic.
În alte cazuri, este mult mai puțin clar, deoarece limbajul nu se deranjează cu acest tip de formalizare, de exemplu, decoratorii din Python sunt adesea descriși prin modul în care ați scrie codul echivalent fără ei, dar din câte știu, nu se spune niciodată în mod explicit: „tu nu ar trebui să compileze decoratorii direct în reprezentarea dvs. intermediară, ci mai degrabă să le traduceți în acest fel în prealabil ”. Unele implementări ale Python pot alege să facă exact asta, dar altele ar fi putut adăuga decoratori ca o caracteristică a reprezentării lor intermediare.