Domande di colloquio per sviluppatori backend (C#/.NET): Guida completa

Milad Bonakdar
Autore
Padroneggia lo sviluppo backend C# e .NET con domande di colloquio essenziali che coprono ASP.NET Core, Entity Framework, Dependency Injection e progettazione del sistema.
Introduzione
C# e .NET si sono evoluti significativamente, diventando un ecosistema potente e multipiattaforma per la creazione di sistemi backend ad alte prestazioni. Con l'avvento di .NET Core (e ora semplicemente .NET 5+), è una scelta eccellente per applicazioni cloud-native, microservizi e soluzioni enterprise.
Questa guida copre le domande essenziali per i colloqui per Sviluppatori Backend specializzati in C# e .NET. Esploreremo i fondamenti del linguaggio, l'architettura di ASP.NET Core, le interazioni con il database tramite Entity Framework e le best practice per aiutarti a prepararti al tuo prossimo colloquio.
Fondamenti del linguaggio C#
1. Qual è la differenza tra struct e class in C#?
Risposta:
- Class: Un tipo di riferimento (allocato nell'heap). Quando si passa un oggetto class a un metodo, si passa un riferimento alla posizione di memoria. Le modifiche all'interno del metodo influenzano l'oggetto originale. Supporta l'ereditarietà.
- Struct: Un tipo di valore (allocato nello stack). Quando si passa uno struct, viene passata una copia dei dati. Le modifiche all'interno del metodo non influenzano lo struct originale. Non supporta l'ereditarietà (ma può implementare interfacce).
- Utilizzo: Utilizzare
structper strutture dati piccole e immutabili che rappresentano un singolo valore (comePoint,Color). Utilizzareclassper la maggior parte degli altri oggetti.
Rarità: Comune Difficoltà: Facile
2. Spiega async e await. Come aiutano con la scalabilità?
Risposta:
async e await sono parole chiave utilizzate per la programmazione asincrona.
- Meccanismo: Quando viene incontrata una parola chiave
await, l'esecuzione del metodo viene sospesa e il thread viene rilasciato nuovamente nel thread pool per gestire altre richieste. Quando l'attività attesa viene completata, l'esecuzione riprende (potenzialmente su un thread diverso). - Scalabilità: In un web server (come Kestrel), i thread sono una risorsa limitata. Se un thread si blocca in attesa di I/O (database, rete), non può gestire altre richieste. Async consente al server di gestire molte più richieste simultanee con meno thread non bloccandoli durante le operazioni di I/O.
Rarità: Molto Comune Difficoltà: Media
3. Cos'è l'Dependency Injection (DI) e come viene implementata in .NET?
Risposta: Dependency Injection è un modello di progettazione in cui le dipendenze di una classe vengono fornite dall'esterno anziché create internamente.
- In .NET: ASP.NET Core ha un contenitore DI integrato. Si registrano i servizi in
Program.cs(oStartup.csnelle versioni precedenti) e li si inietta tramite l'iniezione del costruttore. - Durate:
- Transient: Creati ogni volta che vengono richiesti.
- Scoped: Creati una volta per richiesta client (richiesta HTTP).
- Singleton: Creati la prima volta che vengono richiesti e condivisi da tutte le richieste successive.
Rarità: Molto Comune Difficoltà: Media
4. Qual è la differenza tra IEnumerable<T> e IQueryable<T>?
Risposta:
IEnumerable<T>: Esegue la query in memoria. Se utilizzato con un database (EF Core), recupera tutti i dati dal server alla memoria del client e poi li filtra. Ottimo per LINQ to Objects.IQueryable<T>: Esegue la query in remoto (ad esempio, sul server SQL). Costruisce un albero delle espressioni che viene tradotto in una query SQL. Il filtraggio avviene lato database, il che è molto più efficiente per grandi set di dati.
Rarità: Comune Difficoltà: Media
5. Cosa sono i Metodi di Estensione?
Risposta: I metodi di estensione consentono di "aggiungere" metodi ai tipi esistenti senza creare un nuovo tipo derivato, ricompilare o modificare in altro modo il tipo originale.
- Sintassi: Definiti come metodi statici in una classe statica. Il primo parametro specifica su quale tipo opera il metodo, preceduto dalla parola chiave
this. - Esempio: Aggiunta di un metodo
WordCount()alla classestring.
Rarità: Comune Difficoltà: Facile
ASP.NET Core e Architettura
6. Cos'è Middleware in ASP.NET Core?
Risposta: I middleware sono componenti software che vengono assemblati in una pipeline applicativa per gestire richieste e risposte.
- Pipeline: Ogni componente sceglie se passare la richiesta al componente successivo nella pipeline e può eseguire operazioni prima e dopo che il componente successivo viene invocato.
- Esempi: Autenticazione, Autorizzazione, Logging, Gestione delle eccezioni, Servizio di file statici.
- L'ordine è importante: L'ordine in cui il middleware viene aggiunto in
Program.csdefinisce l'ordine di esecuzione.
Rarità: Molto Comune Difficoltà: Media
7. Spiega la differenza tra .NET Core e .NET Framework.
Risposta:
- .NET Framework: L'implementazione originale, solo per Windows. Matura, ma legata a Windows.
- .NET Core (ora semplicemente .NET): Un'implementazione multipiattaforma, open-source e modulare. Funziona su Windows, Linux e macOS. È ottimizzata per alte prestazioni e distribuzioni cloud.
- Differenze chiave: Supporto multipiattaforma, architettura adatta ai microservizi, prestazioni più elevate, versioni affiancate.
Rarità: Comune Difficoltà: Facile
8. Cos'è Kestrel?
Risposta: Kestrel è un web server multipiattaforma, open-source, event-driven che è incluso di default nei template ASP.NET Core.
- Ruolo: Ascolta le richieste HTTP e le passa all'applicazione.
- Utilizzo: Può essere eseguito standalone (edge server) o dietro un reverse proxy come IIS, Nginx o Apache. L'utilizzo di un reverse proxy è raccomandato per la produzione per gestire la sicurezza, il bilanciamento del carico e la terminazione SSL.
Rarità: Media Difficoltà: Media
9. Come gestisci la Gestione Globale delle Eccezioni in ASP.NET Core?
Risposta: Invece di blocchi try-catch in ogni controller, dovresti utilizzare middleware per la gestione globale delle eccezioni.
UseExceptionHandler: Middleware integrato che cattura le eccezioni, le registra e riesegue la richiesta in una pipeline alternativa (di solito puntando a una pagina di errore o a una risposta API).- Middleware personalizzato: Puoi scrivere middleware personalizzati per catturare le eccezioni e restituire una risposta di errore JSON standardizzata (ad esempio,
ProblemDetails).
Rarità: Comune Difficoltà: Media
Database ed Entity Framework
10. Cos'è Entity Framework Core (EF Core)? Code-First vs. Database-First?
Risposta: EF Core è un Object-Relational Mapper (ORM) per .NET. Consente agli sviluppatori di lavorare con un database utilizzando oggetti .NET.
- Code-First: Definisci prima le tue classi di dominio (entità) e EF Core crea/aggiorna lo schema del database in base a esse utilizzando le Migrazioni. Preferito per nuovi progetti.
- Database-First: Hai un database esistente ed EF Core genera le classi .NET (scaffolding) in base allo schema.
Rarità: Comune Difficoltà: Facile
11. Qual è il problema N+1 in EF Core e come lo risolvi?
Risposta: Il problema N+1 si verifica quando si recupera un elenco di entità (1 query) e quindi si accede a un'entità correlata per ogni elemento in un ciclo, causando N query aggiuntive.
- Soluzione: Utilizzare il Caricamento Eager con il metodo
.Include(). Questo genera unJOINSQL per recuperare i dati correlati in una singola query. - Esempio:
context.Orders.Include(o => o.Customer).ToList();
Rarità: Molto Comune Difficoltà: Media
12. Spiega il Repository Pattern. Perché usarlo con EF Core?
Risposta: Il Repository Pattern media tra i livelli di dominio e di mapping dei dati utilizzando un'interfaccia simile a una collection per accedere agli oggetti di dominio.
- Pro: Disaccoppia l'applicazione dalla specifica tecnologia di accesso ai dati (EF Core), semplifica l'unit testing (può mockare il repository) e centralizza la logica di accesso ai dati.
- Contro/Dibattito:
DbContextdi EF Core è già un'implementazione del Repository/Unit of Work pattern. L'aggiunta di un altro livello a volte può essere ridondante ("astrazione sull'astrazione").
Rarità: Comune Difficoltà: Difficile
API REST e Servizi Web
13. Quali sono i Verbi HTTP e il loro tipico utilizzo?
Risposta:
- GET: Recupera una risorsa. Sicuro e Idempotente.
- POST: Crea una nuova risorsa. Non Idempotente.
- PUT: Aggiorna/Sostituisce una risorsa esistente. Idempotente.
- PATCH: Aggiorna parzialmente una risorsa. Non necessariamente Idempotente (ma di solito lo è).
- DELETE: Rimuove una risorsa. Idempotente.
Rarità: Comune Difficoltà: Facile
14. Qual è la differenza tra 401 Unauthorized e 403 Forbidden?
Risposta:
- 401 Unauthorized: L'utente non è autenticato. Il client deve effettuare il login e riprovare. "Non so chi sei."
- 403 Forbidden: L'utente è autenticato ma non ha il permesso di accedere alla risorsa. "So chi sei, ma non puoi farlo."
Rarità: Comune Difficoltà: Facile
Testing e Best Practice
15. Qual è la differenza tra Unit Test e Integration Test?
Risposta:
- Unit Test: Testa una piccola unità di codice (di solito un metodo) in isolamento. Le dipendenze vengono mockate (utilizzando strumenti come Moq). Veloci e affidabili.
- Integration Test: Testa come diverse parti dell'applicazione lavorano insieme (ad esempio, endpoint API + Database). Più lenti ma verificano il comportamento effettivo del sistema.
Rarità: Comune Difficoltà: Facile
16. Come mocki le dipendenze negli Unit Test?
Risposta: Framework di mocking come Moq o NSubstitute vengono utilizzati per creare implementazioni fake di interfacce.
- Scopo: Isolare la classe in fase di test. Ad esempio, se si testa un
UserService, si mockaIUserRepositoryin modo da non colpire il database reale. - Esempio (Moq):
Rarità: Comune Difficoltà: Media
17. Cosa sono i principi SOLID? Fai un esempio di uno.
Risposta: SOLID è un acronimo per 5 principi di progettazione per rendere il software più comprensibile, flessibile e manutenibile.
- Single Responsibility Principle (SRP)
- Open/Closed Principle (OCP)
- Liskov Substitution Principle (LSP)
- Interface Segregation Principle (ISP)
- Dependency Inversion Principle (DIP)
- Esempio (DIP): I moduli di alto livello non dovrebbero dipendere dai moduli di basso livello. Entrambi dovrebbero dipendere da astrazioni. Questa è la base per la Dependency Injection.
Rarità: Comune Difficoltà: Difficile
18. Cosa sono Boxing e Unboxing? Perché evitarli?
Risposta:
- Boxing: Conversione di un tipo di valore (come
int) in un tipo di riferimento (object). Alloca memoria nell'heap. - Unboxing: Conversione del tipo di riferimento di nuovo nel tipo di valore.
- Prestazioni: Entrambe sono operazioni costose (allocazione di memoria, controllo del tipo). I generics (
List<T>) aiutano a evitare il boxing/unboxing rispetto alle collection più vecchie (ArrayList).
Rarità: Comune Difficoltà: Media
19. Cos'è l'istruzione using in C#?
Risposta:
L'istruzione using fornisce una sintassi conveniente che garantisce l'uso corretto degli oggetti IDisposable.
- Meccanismo: Chiama automaticamente il metodo
Dispose()sull'oggetto quando si esce dal blocco (anche se si verifica un'eccezione). - Sintassi moderna:
using var file = File.OpenRead("path");(non sono necessarie parentesi graffe, eliminato alla fine dello scope).
Rarità: Comune Difficoltà: Facile
20. Spiega il concetto di Middleware nel contesto del pattern "Chain of Responsibility".
Risposta: ASP.NET Core Middleware è un'implementazione classica del pattern Chain of Responsibility.
- Pattern: Una richiesta viene passata lungo una catena di gestori. Ogni gestore decide se elaborare la richiesta o passarla al gestore successivo nella catena.
- Applicazione: In .NET, il
RequestDelegaterappresenta il gestore successivo. I componenti middleware sono concatenati per formare la pipeline di richiesta.
Rarità: Non comune Difficoltà: Difficile



