Preview Image

Most candidates walk into a .NET interview having memorized definitions. They can tell you what the CLR is, recite the difference between value and reference types, and explain garbage collection

Most candidates walk into a .NET interview having memorized definitions. They can tell you what the CLR is, recite the difference between value and reference types, and explain garbage collection in theory. But the moment an interviewer asks a follow-up or frames the question differently, the rehearsed answer falls apart.


That's where most people lose jobs. The developers who get hired aren't necessarily the ones who know the most. They're the ones who understand why things work the way they do well enough to reason through something they've never seen before. This guide is built around that idea.


What Interviewers Are Actually Evaluating


What Interviewers Are Actually Evaluating

Before diving in, it helps to understand what's being assessed behind every question:


  • Conceptual clarity: Do you understand the “why”, not just the “what?”
  • Practical exposure: Have you actually used this in real projects?
  • Communication: Can you explain complex ideas in clear, simple language?

Keep those three filters in mind. The goal isn't to sound smart; it's to sound like someone who's built things, broken things, and learned from both.


If you're also preparing for automation testing roles alongside .NET, our Selenium Interview Questions guide covers the top 30 questions you need to know.


Foundational .NET Interview Questions


Q1. What is the .NET CLR, and what does it actually do?


The Common Language Runtime, or CLR, sits at the heart of every .NET application. When you write C# code, you’re not writing machine instructions directly. Instead, your code complies to Common Intermediate Language (CIL). The CLR takes that CIL, uses its JIT (Just-In-Time) compiler to compile it to native code at runtime.


But execution is just one part. The CLR also handles:


  • Memory management through garbage collection
  • Type safety enforcement
  • Exception handling
  • Thread management

Think of it as the environment your code lives in, not just the thing that runs it.


Q2. What is the difference between value types and reference types?


This is one of the most fundamental distinctions in C#, and it comes up constantly.


Value types hold their data directly. When you create a value type variable, the actual value is stored right there in memory, typically on the stack. If you copy it, you get a brand-new independent copy. Examples include int, bool, double, char, and struct.


Reference types don't hold the data directly. Instead, they hold a reference (basically a memory address) that points to where the data lives on the heap. If you copy a reference type, both variables point to the same data; changing one affects the other. Examples include class, string, array, and object.


You can remember this as: value types are like handing someone a copy of a document. Reference types are like sharing a link to the same document online.


If some of these foundational distinctions feel unfamiliar, brushing up on basic coding concepts can help solidify your understanding before tackling language-specific questions.


Q3. What is boxing and unboxing in C#?


Boxing happens when you wrap a value type inside an object, pushing it onto the heap. Unboxing is pulling the value back out.



The reason why this matters is because of its performance. Boxing causes a heap allocation, and if it happens inside a tight loop, like with older ArrayList collections, the overhead adds up fast. Modern generics like List eliminate this entirely by keeping value types as value types.


Q4. What's the difference between String and StringBuilder?


String in C# is immutable. Every time you modify it, a new string object is created in memory. That's fine for simple operations, but inside a loop, building a large string, every + operator creates a fresh allocation.


StringBuilder solves this by modifying the same buffer in place. It's the right choice whenever you're building strings dynamically; think log formatting, generating SQL, or constructing large reports.


Q5. What is a delegate, and when would you actually use one?


A delegate is essentially a type-safe function pointer. It holds a reference to a method with a specific signature and lets you pass behavior around like data.



Delegates are the backbone of events, callbacks, and LINQ. They let you write code that works with behavior rather than being locked to a specific implementation.


Q6. What are access modifiers in C#?


Access modifiers control visibility and encapsulation. Here's a quick breakdown:


  • Public: Accessible from anywhere
  • Private: Only within the same class
  • Protected: Same class and any derived classes
  • Internal: Within the same assembly only
  • protected internal: Same assembly or derived classes

Choosing the right modifier isn't about security; it's about intentional design. Expose only what needs to be exposed. Everything else should be private by default.


Q7. What's the difference between an interface and an abstract class?


Both define contracts, but they serve different design purposes.


An abstract class can contain implemented methods, constructors, and fields. It expresses a shared base — an "is-a" relationship. An interface defines capability — a "can-do" relationship with no state. Before C# 8, interfaces had zero implementation. From C# 8 onward, interfaces can include default method implementations, but this is the exception, not the rule. A class can implement multiple interfaces, making them ideal when unrelated types need to share a common contract.


The practical constraint: C# allows only single class inheritance, but a class can implement multiple interfaces. If you need shared logic, use an abstract class. If you're defining behavior that many unrelated types might share, use an interface.


Q8. What does the using statement do, and why does it matter? 


The using statement ensures that objects implementing IDisposable are properly cleaned up after use, even if an exception is thrown. Under the hood, it compiles into a try/finally block that calls Dispose(). 



Without using it, you risk resource leaks, especially with database connections, file handles, and network streams. It's one of the easiest best practices to follow and one of the most consequential when ignored.


Q9. What is the difference between const and readonly in C#?


Both prevent a value from being changed, but they behave differently.


  • const is evaluated at compile time and baked directly into the compiled code. It must be assigned at declaration and can only hold primitive values or strings.
  • readonly is evaluated at runtime and can be assigned either at declaration or inside a constructor. It works with any type.

If the value is truly fixed and primitive, like const int MaxRetries = 3;, use const. For anything more complex or that might differ by instance, readonly is the safer choice.


Q10. What is the difference between == and.Equals() in C#?


For value types, both generally check value equality. For reference types, the default behavior diverges.


== on a reference type checks whether both variables point to the same object in memory. .Equals() can be overridden to compare values instead of references.


String is a common source of confusion here. It’s a reference type, but == has been overridden to compare values. For your own custom classes, if you want a value-based comparison, override both.Equals() and GetHashCode() together.


Intermediate .NET Interview Questions


Q11. How does async/await actually work?


The most common misconception is that async/await creates new threads; it doesn’t. It's about freeing the current thread while waiting for an I/O-bound operation to complete.


When execution hits an await, it registers a continuation and hands control back to the caller. When the awaited task finishes, execution resumes, usually on a thread pool thread in ASP.NET Core. In UI apps like WinForms or WPF, however, execution resumes on the original UI thread due to the SynchronizationContext. In library code, use ConfigureAwait(false) to avoid unnecessary context switching.When execution hits an await, it registers a continuation and hands control back to the caller. When the awaited task finishes, execution resumes, usually on a thread pool thread in ASP.NET Core. In UI apps like WinForms or WPF, however, execution resumes on the original UI thread due to the SynchronizationContext. In library code, use ConfigureAwait(false) to avoid unnecessary context switching.



The benefit is scalability. Threads aren't sitting idle waiting for a database or network response; they're free to handle other requests.


Q12. What's the difference between Task and Thread?


A Thread is a low-level OS construct. A Task is a higher-level abstraction representing an asynchronous operation that may or may not involve a dedicated thread.


Tasks are smarter. They use the thread pool, support cancellation, compose cleanly with async/await, and handle continuations naturally. Raw threads give you more control, but at a significant complexity cost. In modern .NET, you should almost always reach for Task first.


Q13. What is dependency injection, and what are the three service lifetimes in .NET?


Dependency injection means a class receives its dependencies from the outside rather than creating them internally. It decouples your code from concrete implementations and makes testing dramatically easier.


.NET's built-in DI container offers three lifetime options:


  • Transient: A new instance is created every time the service is requested
  • Scoped: One instance per HTTP request (or per scope)
  • Singleton: One instance for the entire application lifetime

Getting lifetimes wrong causes subtle bugs. The classic mistake is injecting a scoped service into a singleton which is known as a captive dependency. The scoped service gets captured by the singleton and lives longer than intended, causing stale or incorrect state.


Q14. What is LINQ, and what are the two ways to write it?


LINQ (Language Integrated Query) lets you query collections, databases, XML, and other data sources directly in C# rather than writing raw loops or SQL strings.


Query syntax reads like SQL:



Method syntax uses lambda expressions:



Both compile to identical code. Method syntax is more common in real codebases because it chains naturally and reads well in complex queries.


Q15. What's the difference between IEnumerable and IQueryable?


This one trips up a lot of developers working with Entity Framework.


IEnumerable processes queries in memory on the client side. IQueryable translates queries into expressions that can be executed on the data source, meaning EF generates SQL from your LINQ.


If you accidentally force an IQueryable to evaluate early (turning it into IEnumerable), you pull the entire table into memory before filtering. At scale, that's a serious performance problem that's easy to miss in development.


Q16. What are extension methods, and when should you use them?


Extension methods let you add functionality to existing types without modifying or subclassing them. They're defined as static methods in a static class, with this before the first parameter.



They're ideal for types you don't own, like framework types, where you want to add utility behavior cleanly. Avoid using them as a workaround for poor class design.They're ideal for types you don't own, like framework types, where you want to add utility behavior cleanly. Avoid using them as a workaround for poor class design.


Q17. What are generics in C#, and why do they matter?


Generics let you write type-safe code that works with any data type without rewriting the same logic multiple times.



Without generics, you'd use object and lose type safety, introducing casting, boxing, and runtime errors. With generics, the compiler catches type mismatches at compile time. List, Dictionary, and most of the collections in .NET are generic for exactly this reason.


Q18. What is the difference between throw and throw ex in C#?


This is a subtle but important distinction when handling exceptions.


throw re-throws the current exception and preserves the original stack trace. throw ex re-throws but resets the stack trace to the current location effectively hiding where the exception originally occurred. Almost always use throw by itself. throw ex makes debugging harder because you lose the exact source of the failure.


Advanced .NET Interview Questions


Q19. How does the .NET Garbage Collector work, and what are the three generations?


The GC is generational because most objects die young. It divides the heap into three generations:


Objects that survive a collection get promoted to the next generation. The Large Object Heap (LOH) handles objects over 85KB separately. LOH collections are costly and can cause fragmentation, which is worth watching in memory-intensive apps.


  • Gen 0: Short-lived objects. Collected very frequently and cheaply.
  • Gen 1: Objects that survived Gen 0. Acts as a buffer between short and long-lived objects.
  • Gen 2: Long-lived objects. Collected infrequently but expensively.

Q20. What's the difference between managed and unmanaged resources?


 Managed Unmanaged 
Examples .NET objects, arrays, strings File handles, DB connections, COM objects 
Cleanup Handled by GC automatically Must be released manually 
Interface — IDisposable 

Managed resources are cleaned up by the garbage collector without you doing anything. Unmanaged resources sit outside the GC's awareness if you don't release them explicitly through Dispose() or using, they stay open until the process ends, or the OS reclaims them.


Q21. What is the difference between Dispose and Finalize?


Dispose is called explicitly either by your code or by a using block. It runs immediately and deterministically.



Finalize (a destructor in C#) is called by the GC at some indeterminate time before memory is reclaimed. It's a fallback safety net, not a first-line cleanup strategy.


You should always prefer Dispose. Objects with finalizers are more expensive to collect because they go through an extra finalization queue before their memory is freed. If you implement a finalizer, suppress it inside Dispose once cleanup is done.


Q22. What is middleware in ASP.NET Core?


Middleware are components that forms a pipeline for processing HTTP requests and responses. Each component receives the request, optionally does something with it, then either passes it to the next component or short-circuits the pipeline.



Registration order matters significantly. Logging should come before authentication. Authentication before authorization. Routing before endpoint mapping. Getting the order wrong produces subtle, hard-to-debug behavior.



Getting this order wrong, for example, placing UseAuthorization() before UseAuthentication(), means the app checks permissions before knowing who the user is, breaking access control entirely.


Once your ASP.NET Core APIs are built, use API testing tools to test them properly.


Q23. What are records in C#, and how do they differ from classes?


Records are reference types designed for immutable data. They automatically provide value-based equality, a readable ToString(), and a concise syntax.



Two Person records with the same values are considered equal by default. Two class instances with the same values are not unless you manually override equality. Records are ideal for DTOs, value objects, and any data you want to treat by value rather than identity. Records also support with expressions for non-destructive mutation, creating a modified copy without changing the original:



Q24. What is the difference between Task.WhenAll and Task.WhenAny?


Task.WhenAll waits for every task in the set to complete before continuing. Task.WhenAny continues as soon as the first task finishes.



When all is the right choice for parallel independent operations, where you need all results. WhenAny fits timeout patterns or scenarios where you're racing multiple data sources and only need the fastest response.


Q25. What is reflection in .NET, and what are the performance trade-offs?


Reflection lets you inspect and interact with types at runtime, such as reading metadata, invoking methods, and creating instances without knowing the type at compile time.



It's powerful and used heavily by frameworks, serializers, and DI containers. The cost is real performance overhead; reflection bypasses compile-time optimizations and is noticeably slower than direct calls. In hot code paths, cache reflected members or use compiled expression trees as a faster alternative.


Also note: reflection is unavailable in AOT-compiled .NET apps (e.g., .NET Native AOT). Use source generators as a compile-time alternative instead.


.NET Performance and Memory Questions


Q26. What is Span, and how does it help with performance?


Span is a stack-allocated view over a contiguous block of memory; an array, a string, or even unmanaged memory. It lets you slice and process data without creating any new allocations.



It's particularly valuable in parsing-heavy code where you'd otherwise be creating substrings constantly. The constraint is that Span is a ref struct; it can only live on the stack, so you can't store it in a class field or use it across async boundaries.


Q27. What causes memory leaks in a .NET application despite the GC?


The GC can only collect objects that nothing is referencing. Memory leaks in .NET happen when something unexpected keeps a reference alive.


Common culprits:


  • Unsubscribed event handlers: The event publisher holds a reference to the subscriber, preventing collection
  • Static collections that grow indefinitely: Static fields are rooted for the application's lifetime
  • Unmanaged resources not disposed: GC doesn't touch file handles or database connections
  • Captured variables in long-lived closures: Holding more in scope than intended

Diagnosis usually involves memory profilers like dotMemory or PerfView, and analyzing heap dumps for objects that are still rooted but shouldn't be.


Q28. What is the difference between a deep copy and a shallow copy?


A shallow copy duplicates the object itself but leaves reference-type fields pointing to the same underlying objects. A deep copy recursively duplicates everything, including all referenced objects.


MemberwiseClone() produces a shallow copy. For a true deep copy, you typically serialize and deserialize the object or write explicit cloning logic. Getting this wrong leads to a particularly nasty class of bugs; you modify what you think is an independent copy, and something else changes unexpectedly.


Q29. What is the difference between struct and class in C#?


Feature StructClass
Type Value type Reference type 
Memory Stack (typically) Heap 
Inheritance Not supported Supported 
Default nullability Non-nullable Nullable 
Best for Small, simple data Complex behavior and state 

Structs are great for small, frequently created data structures like Point, Color, or DateTime, where heap allocation overhead matters. But large structs that are copied repeatedly can hurt performance instead of helping it. Know the trade-offs before reaching for one.


Q30. What is ArrayPool, and why would you use it?


ArrayPool lets you rent and return arrays instead of allocating new ones every time. It's part of .NET's memory pooling infrastructure.



This matters in high-throughput scenarios like network servers, parsers, and serializers where constant allocation creates significant GC pressure. The trade-off is disciplined: you must return the buffer when done, and you should never assume it's been zeroed out between rentals.


Conclusion


.NET interviews are more about testing depth of your knowledge. You might pass the screening call by memorizing definitions, but it won’t get you hired. This interview checks whether you understand why the platform works the way it does and that you’ve actually built things with that knowledge. These are .NET interview questions that you might encounter in your interview. Use this guide to understand concepts and practice questions to know where you stand.


The demand for .NET developers continues to grow as more businesses invest in high-tech software to stay competitive, making this one of the most future-proof skill sets you can build.


FAQs About .NET Interview Questions


Q. How many .NET questions should I actually prepare for?

Depth beats quantity. Genuinely understanding 30-40 concepts across CLR, memory, async, and architecture will serve you far better skimming a hundred questions.


Q. Should I focus on the .NET framework or modern .NET?

Focus on .NET 6+ and beyond, but understand the legacy landscape. Many enterprise codebases still run on .NET Framework, and interviewers often ask about migration experience.


Q. Do I need to memorize syntax for interviews?

Not verbatim, but you should be comfortable sketching a rough implementation. Struggling to write a basic async method raises doubts about hands-on experience.


Q. How important is system design for .NET roles?

For mid-to-senior positions, it's significant. Be ready to discuss API architecture, caching strategies, database access patterns, and designing for scale.


Q. What’s the best way to prepare beyond reading Q&As?

Build something real. A small ASP.NET Core API with DI, EF Core, async patterns, and proper error handling will teach you more than any list of questions and give you real experiences to talk about in the room.

Respond to this article with emojis
You haven't rated this post yet.