NOU 🚀 HTML & CSS de la ZERO este acum LIVE! Prinde reducerea de lansare.

Top 5 întrebări de interviu pentru C# developer

Postat 27 Iulie, 2025
Top 5 întrebări de interviu pentru C# developer

Interviurile tehnice sunt de departe cel mai important pas din procesul de recrutare pentru un dezvoltator software, indiferent de tehnologia sau limbajul de programare de care vorbim.

E etapa crucială unde trebuie să dai tot ce poți pentru a convinge intervievatorii că deții setul de cunoștințe necesare pentru a face parte și aduce plusvaloare în echipele lor de dezvoltare.

În cele ce urmează o să trecem prin unele din cele mai frecvente întrebări regăsite în interviurile tehnice pentru C# developer și o să analizăm, pentru unele din ele, unghiurile din care intervievatorii pun aceste întrebări.

Hai să începem.

1. Care sunt diferențele dintre o clasă abstractă și o interfață?

Una din cele mai frecvente întrebări e cea despre diferențele dintre o clasă abstractă și o interfață, deși în versiunile recente de C#, întrebarea asta și-a cam pierdut rostul, pentru că funcțional vorbind, nu mai sunt atât de multe diferențe între ele precum erau în trecut.

Vei găsi în alte articole sau răspunsuri ale LLM-urilor argumente precum:

  • Interfețele nu pot avea proprietăți
  • Interfețele nu pot avea metode cu implementare

Ambele puncte erau valide în trecut, dar nu mai sunt din păcate în versiunile recente de C#.

Interfețele pot avea acum și proprietăți și chiar și metode cu implementare. Un lucru care e foarte neobișnuit într-un limbaj de programare orientat pe obiect.

Uite un exemplu:

interface IVehicle
{
  public Fuel Fuel { get; set; } // proprietate validă
  void Drive();
  void StartEngine()
  {
    Console.WriteLine("Vehicle engine starts");	// metodă cu implementare
  }
}

Chiar și așa, metodele de interfețe cu implementare sunt folosite extrem de rar, spre deloc.

Personal nu am văzut niciodată pe undeva într-o aplicație de producție, dar cert e că se poate.

Ele se pretează mai degrabă celor care dezvoltă biblioteci, dar poate dezvoltăm mai mult despre asta cu altă ocazie.

Acum revenind, răspunsul e că diferențele sunt mai degrabă de semantică decât funcționale.

Atunci când folosim o interfață, expunem codul nostru prin ceea ce poartă simbolic numele de “contract”, unde termenii acestui contract sunt reprezentați de metodele publice ale interfeței.

Codul client va folosi implementările tale prin intermediul acestui contract, fără să știe detaliile implementărilor sau unde se află ele.

Pe când semantica unei clase abstracte e puțin diferită.

Atunci când întâlnim o clasă abstractă, de obicei vine cu câteva metode preimplementate, iar noi trebuie doar să umplem câteva goluri prin implementarea metodelor declarate abstract.

Deși, din nou, același lucru îl poți face și prin intermediul unei interfețe, această practică s-a păstrat în rândul programatorilor și a cam rămas singurul mod prin care evaluăm decizia folosirii uneia sau celeilalte.

Un alt lucru pe care ar fi bine să-l iei în calcul, e faptul că, în C#, o clasă poate implementa mai multe interfețe, dar nu poate extinde decât o singură clasă.

Motivul pentru care există restricția asta se numește Diamond Problem, poți citi mai multe despre asta aici.

De asemenea, asta poate să fie încă una din întrebările de interviu, ce pot deriva din întrebarea inițială, așa că ține bine minte toate aceste detalii.

3. Care este diferența dintre un reference type și un value type?

Asta e o intrebare ce vine pentru verificarea nivelului de înțelegere pentru sistemele de typing în cazul limbajelor denumite strongly typed, așa cum este și C#.

Diferențele principale între ele sunt, pe de o parte zona de memorie unde sunt stocate datele (stack pentru tipuri valorice, heap pentru referințe), iar pe de altă parte, modul în care se comportă aceste tipuri când sunt pasate ca argumente între metode.

Pe scurt, o metodă ce primește ca argument un tip valoric, va primi o copie a valorii respective, pe când o metodă ce primește o referință, va primi o copie a referinței către același obiect din memorie.

Asta va avea un efect diferit a modului în care codul interacționează cu datele, în sensul că, în cazul referinței, obiectul din memorie va fi același și deci va putea fi alterat și de o altă linie de cod, pe când în cazul unui tip valoric, valoarea fiind copiată de fiecare dată, cea inițială rămânând neafectată de schimbări ulterioare.

Uite un exemplu care te-ar putea ajuta să înțelegi mai ușor.

var number = 3;
var sum = Sum(number + 10);

int Sum(int a, int b)
{
  return a + b;
}

var person = new Person("Mihai");
void PrintName(Person person)
{
  Console.WriteLine(person.Name);
}
Tipuri valorice vs. tipuri referință în C#

Dacă vrei să afli și mai multe despre acest subiect, am scris un întreg articol aici.

3. Care e diferența între const și readonly?

Aceștia reprezintă 2 modificatori folosiți destul de frecvent în C# și e important să înțelegem comportamentul lor.

Par similari la prima vedere, dar există anumite diferențe.

O constantă are nevoie ca valoarea să-i fie atribuită direct la momentul declarării și condiția asta e verificată în procesul de compilare. Adică în timp ce scrii codul.

De asemenea constantele sunt implicit și statice, astfel că pot fi apelate direct pe clasă fără a avea nevoie de un obiect.

O variabilă readonly e disponibilă doar la citire (de-aici și read only), până aici nimic diferit față de constantă.

Unei variabile readonly, la fel ca și în cazul unei constante, nu i se poate atribui o valoare decât la momentul declarării sau în timpul execuției constructorului. În afara acestor 2 situații, ea nu poate fi schimbată niciodată.

4. Explică rolul mecanismului de garbage collection

Garbage collection e mecanismul prin care mediul de execuție se asigură de curățarea automată a memoriei.

Pe măsură ce codul nostru se execută, sunt create în memorie sume impresionante de obiecte, pe care ulterior trebuie să le ștergem pentru a nu ocupa inutil.

În limbaje precum C sau C++ operațiunea asta trebuie făcută în mod intenționat de către dezvoltator, pe când în C# acest lucru se întâmplă automat, iar dezvoltatorul nu trebuie să se gândească prea mult la asta.

Acesta e un subiect care ar putea genera întrebări ulterioare în interviu, precum:

Care e diferența dintre cod “managed” și “unmanaged”?

Codul gestionat e cel a cărui memorie utilizată poate fi curățată în mod automat de mecanismul de garbage collection, pe când cel negestionat (unmanaged) e cel care nu dispune de această facilitate.

Cum e posibil asta?

Ei bine, codul a cărui memorie e gestionată automat e cel care folosește doar resurse din cadrul mediului de execuție.

În momentul în care sunt folosite resurse sau componente externe ce nu țin de mediul de execuție (runtime), precum baze de date, fișiere de pe disc, apeluri HTTP etc., memoria ocupată de aceste componente trebuie să fie curățată de alte mecanisme alte sistemului de operare, iar ele fac parte din categoria de cod negestionat (unmanaged).

Descrie rolul cuvântului cheie using

Rolul cuvântului cheie using e acela de a semnala mediului de execuție că urmează să folosim resurse din afara lui și ar trebui să notifice sistemul de operare să curețe mai departe după noi.

Acest lucru se face prin apelarea metodei Dispose() care e disponibilă pe toate obiectele în C#.

Acest apel va notifica sistemul de operare să curețe resursele negestionate folosite de mediul de execuție în momentul în care blocul de cod using va fi părăsit.

Uite un exemplu:

using (var connection = new DbConnection())
{
	//.. apelează baza de date
} // aici se apelează connection.Dispose() pentru închiderea conexiunii 
  // și eliberarea memoriei

5. Cum se execută codul de C#?

Asta e o întrebare ce poate avea diferite nuanțe, dar dacă răspunsul tău va cuprinde toate etapele prin care trece codul, de la C#, la cod mașină, e imposibil să nu acoperi toate unghiurile la care s-ar putea gândi intervievatorul.

Codul de C# trece, în procesul lui de execuție, prin mai multe transformări:

  1. Compilare

Compilarea e procesul prin care codul scris de dezvoltator e analizat și convertit din limbajul sursă (C#), în ceea ce poartă numele de limbaj intermediar (intermediate language).

Formatul fișierelor de limbaj intermediar este .dll.

  1. Interpretarea și execuția limbajului intermediar

Ai putea spune că acest pas 2, pare să grupeze defapt 2 pași în unul singur și ai avea dreptate.

Dar interpretarea și execuția codului în limbaj interemdiar se întâmplă întotdeauna împreună, de-asta le-am și grupat sub același pas.

Deși a suferit deja o transformare, codul nostru de C# nu poate fi citit și executat de sistemul hardware nici sub acest format, din mai multe considerente, dar cel mai important ar fi acela că modul în care se face transmiterea instrucțiunilor la procesor depinde mult de arhitectura sistemului de operare și a procesorului.

În momentul în care se începe execuția codului de către procesor, mediul de execuție pornește un al doilea compilator ce poartă numele de Just in Time Compiler sau compilator în timp real, ce convertește codul din limbaj intermediar în limbaj mașină și îl dă procesorului pentru execuție.

Uite și un grafic care să te ajute să înțelegi mai bine secvența pașilor.

Etapele execuției codului de C#

De la această întrebare, discuția mai poate devia la întrebări despre tipurile de erori întâlnite, de exemplu.

Acestea sunt de 2 feluri:

  • Erori de compilare, în cazul pasului 1
  • Excepții, în cazul pasului 2

Și aici îți pot veni în ajutor, pentru că am scris un articol întreg pe tema excepțiilor aici.

Concluzie

Interviurile tehnice sunt în general extrem de solicitante, chiar și pentru cei cu senioritate mai ridicată, pentru că te fac să sapi adânc în setul tău de cunoștințe și să scoți detalii și explicații logice despre lucruri la care nu te gândești în mod uzual atunci când scrii cod.

Lista de întrebări de interviu acoperită în acest articol e una destul de succintă, dar sunt întrebările la care eu consider că greșesc cei mai mulți oameni care sunt la nivelul de junior sau middle.

Uite alte câteva puncte de care să ții cont atunci când mergi la un interviu tehnic:

  • Nu-ți fie frică să pui întrebări adiancete de clarificare, pentru a înțelege exact ce se caută.
  • Nimeni nu răspunde corect la toate întrebările dintr-un interviu tehnic. Notează-le pe cele la care nu te-ai descurcat și caută răspunsurile după interviu sau chiar cere răspunsul de la intervievator.
  • Cei mai mulți intervievatori nu caută să-ți pună bețe în toate, ba chiar încearcă să te ghideze spre răspunsul corect, trebuie doar să fii atent.
  • Dacă ceva îți e complet necunoscut spune din prima “nu știu”, nu încerca să vorbești pe lângă subiect doar ca să pară că oferi un răspuns.
  • Pe măsură ce mergi la mai multe interviuri îți vei forma răspunsuri din ce în ce mai coerente și va deveni puțin mai ușor de fiecare dată.

Cam atât pe azi, succes la interviu și ne auzim data viitoare.

Hai în comunitate

Strategii de carieră și concepte tehnice explicate pe înțelesul tău.