30 .NET Interview Questions Every Developer Should Know (2 Years Exp)
Preparing for a mid-level .NET interview? Here are 30 must-know questions on C#, async/await, EF Core, DI, and memory management — with clear answers and tips.
If you have around two years of .NET experience and you’re preparing for your next interview, you already know the basics — but interviewers at the mid-level bar you on depth, not just awareness. They want to know why, not just what.
I’ve compiled the 30 most important questions you’ll likely face, grouped by topic, with clear answers and the real insight interviewers are looking for.
Core .NET & CLR
1. What is the difference between .NET Framework, .NET Core, and .NET 5+?
.NET Framework is the original Windows-only runtime, still maintained but no longer receiving major new features (latest: 4.8). .NET Core was the cross-platform, open-source successor. From .NET 5 onward, Microsoft unified both into a single platform — simply called “.NET”. Today, .NET 8 is the current Long-Term Support (LTS) version.
Interview tip: Don’t confuse “.NET Core” with “.NET 5+”. If asked about migration, the answer is: move to .NET 8.
2. What does the CLR do?
The Common Language Runtime (CLR) is .NET’s execution engine. It:
Compiles your C# code’s Intermediate Language (IL) to native code via JIT (Just-In-Time) compilation
Manages Garbage Collection
Handles exceptions, type safety, and thread management
Modern .NET also supports AOT (Ahead-of-Time) compilation for scenarios where startup time matters, like cloud functions or mobile apps.
3. What is the difference between Value Types and Reference Types?
Value Types (int, bool, struct, enum) are stored on the stack. Assigning them creates a full copy.
Reference Types (class, string, array, interface) store a reference on the stack, but the actual object lives on the heap. Assigning copies the reference, not the data.
Common trick question: Where does a
structinside aclasslive? It lives on the heap alongside its parent object.
4. What are boxing and unboxing?
Boxing converts a value type to object, which causes a heap allocation. Unboxing casts it back.
int x = 42;
object o = x; // boxing — heap allocation
int y = (int)o; // unboxingThis is a hidden performance trap in hot paths. Always prefer generics (List<T>) over ArrayList to avoid it.
5. What is LINQ and what is deferred execution?
LINQ (Language Integrated Query) lets you query collections with readable, composable syntax. The key concept is deferred execution — the query doesn’t run when you define it; it runs when you consume it (.ToList(), .Count(), foreach).
var query = list.Where(x => x > 5); // not executed yet
var result = query.ToList(); // executes nowCalling .ToList() too early wastes memory; calling it too late can cause multiple DB round trips in EF Core.
6. What is the difference between IEnumerable, IQueryable, and IList?
Interface Where it runs Use case IEnumerable<T> In memory Iterating in-memory collections IQueryable<T> Database (SQL) EF Core queries — builds expression trees IList<T> In memory Random access, add/remove
This is one of the most frequently asked EF Core questions.
IQueryablekeeps your filter on the DB;IEnumerablepulls everything to memory first.
OOP & C# Language
7. What are the 4 pillars of OOP?
Encapsulation — hiding internal state with access modifiers (
private,protected)Inheritance — reusing behavior via
class Dog : Animal {}Polymorphism — same interface, different behavior (
virtual/override, method overloading)Abstraction — exposing only what’s necessary via abstract classes and interfaces
8. What is the difference between an abstract class and an interface?
Abstract Class Interface Implementation Can have method bodies Default impls from C# 8+ only Constructors ✅ Yes ❌ No Fields ✅ Yes ❌ No Inheritance Single Multiple
Use an abstract class when sharing code between related types. Use an interface when defining a contract that unrelated types should fulfill.
9. What is the difference between override and new?
override replaces the base method in the virtual dispatch table — polymorphism works correctly.new hides the base method. It only takes effect when the variable type is the derived class.
Animal a = new Dog();
a.Speak(); // override → Dog.Speak() runs
// new → Animal.Speak() runs10. What are delegates and events?
A delegate is a type-safe function pointer. An event wraps a delegate and restricts invocation to the declaring class (preventing outside callers from firing the event).
public delegate void Notify(string message);
public event Notify OnComplete;Built-in shortcuts: Action (no return), Func<T> (with return), EventHandler.
11. What are SOLID principles?
Letter Principle Key idea S Single Responsibility One class, one reason to change O Open/Closed Extend behavior without modifying existing code L Liskov Substitution Subtypes must be substitutable for base types I Interface Segregation Many focused interfaces > one fat interface D Dependency Inversion Depend on abstractions, not concrete implementations
At the 2-year level, you’ll almost always be asked about SRP and DIP with concrete examples.
12. What is the difference between == and .Equals()?
For value types, both compare values. For reference types, == checks reference equality by default, while .Equals() can be overridden for value comparison (and string does override it).
For safe string comparison, always use:
string.Equals(a, b, StringComparison.OrdinalIgnoreCase)Follow-up: Overriding
.Equals()requires also overridingGetHashCode()to maintain the contract.
13. What are Generics and why should you use them?
Generics allow writing type-safe, reusable code without casting or boxing:
public T Max<T>(T a, T b) where T : IComparable<T>
=> a.CompareTo(b) >= 0 ? a : b;Know the key constraints: where T : class, struct, new(), IInterface, BaseClass.
Async / Await
14. How does async/await work?
async/await is syntactic sugar for the Task-based Asynchronous Pattern. When you await a task, the current thread is released back to the pool — no blocking — and the method resumes when the task completes.
public async Task<string> FetchDataAsync() {
var data = await httpClient.GetStringAsync(url);
return data;
}Behind the scenes, the compiler generates a state machine to handle suspension and resumption.
15. When should you use Task.Run vs async/await?
I/O-bound work (DB call, HTTP request): use
async/await— no extra thread neededCPU-bound work (heavy computation): use
Task.Runto offload to a thread pool thread
Don’t wrap I/O operations in Task.Run — it wastes a thread.
16. What causes async deadlocks and how do you prevent them?
Calling .Result or .Wait() on a Task in a synchronization-context-aware environment (classic ASP.NET, WPF, WinForms) can deadlock: the main thread blocks waiting for a continuation that needs the main thread to run.
Prevention:
Always use
awaitUse
ConfigureAwait(false)in library codeNever block async code with
.Result
17. What is async void and why should you avoid it?
async void methods can’t be awaited and exceptions they throw cannot be caught by the caller — they surface as unhandled exceptions.
The only acceptable use is event handlers:
private async void Button_Click(object sender, EventArgs e) { ... }Always use async Task instead.
Entity Framework Core
18. What is EF Core and what is Code First vs DB First?
EF Core is an ORM that maps C# classes to database tables.
Code First: define your C# models → generate the DB via migrations (
Add-Migration,Update-Database)DB First: existing DB → scaffold C# models with
Scaffold-DbContext
Most modern projects use Code First because it keeps schema changes in version control.
19. What is the N+1 query problem?
It happens when loading a list of entities triggers a separate query per entity for a related property:
// BAD: 1 query for orders + N queries for customers
foreach (var order in orders)
Console.WriteLine(order.Customer.Name); // lazy load!// GOOD: single JOIN query
var orders = context.Orders.Include(o => o.Customer).ToList();Use .Include() for eager loading or .AsSplitQuery() for large collection includes.
20. What is the difference between Eager, Lazy, and Explicit Loading?
Type How Risk Eager .Include() at query time None Lazy Auto-loads on property access (requires virtual + proxy) Hidden N+1 Explicit context.Entry(e).Reference().Load() None
Lazy loading is disabled by default in EF Core. You enable it with UseLazyLoadingProxies().
Memory & Performance
21. What is the difference between Stack and Heap?
Stack Heap Stores Value types, method frames Reference type objects Management Auto (LIFO) Garbage Collector Speed Faster Slower Size Limited (~1MB) Large
22. How does Garbage Collection work in .NET?
The GC uses a generational model to collect unreachable objects:
Gen 0: Short-lived objects. Collected frequently and cheaply.
Gen 1: Medium-lived. Acts as a buffer.
Gen 2: Long-lived (static data, caches). Expensive full GC.
Large objects (≥85KB) go directly to the Large Object Heap (LOH), which is rarely compacted.
23. What is IDisposable and when should you implement it?
Use IDisposable to release unmanaged resources (file handles, DB connections, sockets) deterministically — without waiting for the GC.
using var connection = new SqlConnection(connectionString);
// Dispose() is called automatically at end of blockImplement it in your own classes when they hold unmanaged resources or other IDisposable objects.
24. What is the difference between String and StringBuilder?
string is immutable — every concatenation creates a new heap object. StringBuilder is mutable and appends into a buffer.
// Bad for loops — creates 1000 objects:
string result = “”;
for (int i = 0; i < 1000; i++) result += i;// Good — single buffer:
var sb = new StringBuilder();
for (int i = 0; i < 1000; i++) sb.Append(i);Rule of thumb: use StringBuilder when concatenating in loops with 5+ iterations.
Architecture & Patterns
25. What is Dependency Injection in .NET?
DI is a pattern where dependencies are provided to a class rather than created inside it. .NET has a built-in DI container:
builder.Services.AddScoped<IProductService, ProductService>();
builder.Services.AddSingleton<IMemoryCache, MemoryCache>();This decouples your code from concrete implementations, making it testable and maintainable.
26. What are the three DI lifetimes?
Lifetime Instance created Use for Transient Every injection Lightweight, stateless services Scoped Once per HTTP request DbContext, per-request services Singleton Once per app lifetime Configuration, caches
Captive dependency: injecting a Scoped service into a Singleton causes bugs — the Scoped instance lives as long as the Singleton.
27. What is middleware in ASP.NET Core?
Middleware is a pipeline component that processes HTTP requests/responses. Each component can process the request, pass it along, or short-circuit.
app.Use(async (context, next) => {
// Before next middleware
await next();
// After next middleware
});Order matters: Authentication → Authorization → Routing → Endpoint.
28. What is the Repository Pattern?
The Repository Pattern abstracts data access behind an interface, decoupling your business logic from EF Core or SQL details:
public interface IProductRepository {
Task<Product> GetByIdAsync(int id);
Task AddAsync(Product product);
}It makes unit testing easy — you can mock the repository. Note: with EF Core’s DbContext already being an abstraction, a generic repository is often overkill. Know this debate.
29. What is Reflection and what are its downsides?
Reflection allows inspecting and interacting with types at runtime — reading attributes, invoking methods dynamically, creating instances.
var type = typeof(MyClass);
var properties = type.GetProperties();
var instance = Activator.CreateInstance(type);Used by DI containers, JSON serializers, ORMs. Downside: it’s slow. Cache reflected members, and in .NET 6+ consider source generators as a compile-time alternative.
30. What design patterns have you used in .NET?
At 2 years experience, you should be comfortable with:
Repository — abstract data access
Factory — encapsulate object creation logic
Strategy — swap algorithms at runtime (e.g., different discount strategies)
Decorator — add behavior without modifying the class (e.g., caching decorator)
Observer/Event — .NET’s built-in event system
Singleton — via DI container, not hand-rolled
Final Thoughts
1. Know your “why”
Mid-level interviews are about trade-offs. Don’t just say what something is — say when and why you’d use it.
2. Be honest about gaps
If you don’t know something deeply, say “I know the concept at a high level — I haven’t used it hands-on yet.” Interviewers respect honesty over overconfidence.
3. Revisit your own project
You’ll almost certainly be asked “walk me through a project you built.” Prepare a 2-minute story covering the problem, your approach, tech choices, and what you’d do differently.
4. Practice writing code without an IDE
Bring a notebook or practice on paper/whiteboard. Simple LINQ queries, an async method, or a small class hierarchy are common live coding asks.
Good luck with your interview! If this helped you, consider sharing it with other .NET developers who are preparing.
Stay Updated
Follow me for more design tips and tools! ✨
🐙 GitHub: Follow me for more web development resources.
🔗 LinkedIn: Connect with me for tips and tricks in coding.
✍️ Medium: Follow me for in-depth articles on web development.
📬 Substack: Dive into my newsletter for exclusive insights and updates:
🌐 Bento — Explore all my work in one place.
🧭 Linktree — Access my resources, blogs, and social links easily.
Tags: dotnet, csharp, interview, programming, softwaredevelopment


