Skip to main content

Mid C# Interview Questions

Curated Mid-level C# interview questions for developers targeting mid positions. 40 questions available.

Last updated:

C# Interview Questions & Answers

Skip to Questions

Welcome to our comprehensive collection of C# interview questions and answers. This page contains expertly curated interview questions covering all aspects of C#, from fundamental concepts to advanced topics. Whether you're preparing for an entry-level position or a senior role, you'll find questions tailored to your experience level.

Our C# interview questions are designed to help you:

  • Understand core concepts and best practices in C#
  • Prepare for technical interviews at all experience levels
  • Master both theoretical knowledge and practical application
  • Build confidence for your next C# interview

Each question includes detailed answers and explanations to help you understand not just what the answer is, but why it's correct. We cover topics ranging from basic C# concepts to advanced scenarios that you might encounter in senior-level interviews.

Use the filters below to find questions by difficulty level (Entry, Junior, Mid, Senior, Expert) or focus specifically on code challenges. Each question is carefully crafted to reflect real-world interview scenarios you'll encounter at top tech companies, startups, and MNCs.

Questions

40 questions
Q1:

What is the purpose of the volatile keyword?

Mid

Answer

The volatile keyword tells the compiler that a variable may be modified by multiple threads.

It prevents certain optimizations and ensures every read returns the most recent value.

Quick Summary: volatile tells the compiler and CPU not to cache a variable — always read it fresh from memory. Without it, the CPU might cache a value in a register and miss updates from another thread. Use for simple shared flags. For anything complex, use lock or Interlocked instead.
Q2:

What is the difference between abstract class and interface?

Mid

Answer

Abstract class: Can contain both implementation and abstraction.

Interface: Defines only the contract with no implementation (in traditional C#).

A class can inherit one abstract class but implement multiple interfaces.

Quick Summary: Abstract class: can have implementation, fields, and constructors — a class can inherit only one. Interface: defines only a contract with no implementation (historically) — a class can implement many. Use abstract class for shared behavior. Use interface for capabilities that unrelated types can share.
Q3:

What is a virtual method?

Mid

Answer

A virtual method allows derived classes to override behavior and provide their own implementation.

Quick Summary: A virtual method has a default implementation in the base class but can be overridden by subclasses. Mark it virtual in the parent, use override in the child. If not overridden, the base version runs. This is the foundation of runtime polymorphism in C#.
Q4:

What is the difference between Finalize and Dispose?

Mid

Answer

Finalize: Called by the garbage collector.

Dispose: Invoked manually to release unmanaged resources deterministically.

Quick Summary: Dispose is the right approach — call it yourself or use using, runs immediately, deterministic. Finalize (destructor) is called by the GC at an unknown time — you cannot control when. Implement both via the Dispose pattern when your class owns unmanaged resources.
Q5:

What is the difference between shallow copy and deep copy?

Mid

Answer

Shallow copy: Copies only references of reference-type fields.

Deep copy: Creates a fully independent copy of the entire object graph.

Quick Summary: Shallow copy duplicates the top-level object but shares references to nested objects — change a nested object in the copy and the original is affected. Deep copy duplicates everything recursively — fully independent. C# has no built-in deep copy; use serialization or manual cloning.
Q6:

What is reflection in C#?

Mid

Answer

Reflection allows inspecting metadata and interacting with types, methods, and properties at runtime.

Quick Summary: Reflection lets your code inspect and interact with types at runtime — read class names, get methods, invoke them, read attributes, create instances dynamically. Used heavily in ORMs, serializers, DI containers, and test frameworks. Powerful but slow — avoid in hot code paths.
Q7:

What is dynamic type in C#?

Mid

Answer

The dynamic type skips compile-time checking and resolves member access at runtime.

Quick Summary: dynamic skips compile-time type checking entirely — the type resolves at runtime. Useful for COM interop, working with JSON of unknown shape, or calling methods on unknown types at compile time. But you lose IntelliSense and type errors only surface at runtime.
Q8:

What is the difference between public API and internal API in C#?

Mid

Answer

Public API: Accessible from any assembly.

Internal API: Accessible only within the same assembly.

Quick Summary: public API is accessible from any assembly — your external contract. internal API is only accessible within the same assembly — useful for sharing code between classes without exposing it to consumers. Use InternalsVisibleTo to grant test projects access to internal members.
Q9:

What is an assembly in .NET?

Mid

Answer

An assembly is a deployable unit containing compiled code, metadata, and resources.

It is typically a DLL or EXE file.

Quick Summary: An assembly is a compiled .NET file — usually a .dll or .exe. It is the unit of deployment and versioning. It contains compiled IL code, a manifest with metadata, and optional resources. Multiple namespaces can live in one assembly; one namespace can span multiple assemblies.
Q10:

What is the purpose of the params keyword?

Mid

Answer

The params keyword allows passing a variable number of arguments to a method without explicitly creating an array.

Quick Summary: params lets you pass a variable number of arguments without wrapping them in an array. The method receives them as an array, but callers write Sum(1, 2, 3) instead of Sum(new int[] { 1, 2, 3 }). Must be the last parameter in the signature, and only one params per method.
Q11:

What is an explicit interface implementation?

Mid

Answer

Explicit interface implementation allows a class to implement multiple interface methods with the same name without conflict.

The implemented method is accessible only through an interface reference.

Quick Summary: When a class implements two interfaces with a method of the same name, explicit implementation handles each separately. Written as void IInterface.Method() with no access modifier — accessible only through an interface reference, not the class directly. Resolves ambiguity cleanly.
Q12:

What is the difference between readonly field and property?

Mid

Answer

Readonly field: Assigned only during declaration or constructor.

Property: Encapsulates logic and allows controlled read/write through getters and setters.

Quick Summary: A readonly field can only be set during declaration or in the constructor — simple and fast, no logic. A property get/set lets you add computation, lazy init, or validation. Properties are more flexible; readonly fields are simpler when you just need an immutable value with no extra logic.
Q13:

What is an unsafe context in C#?

Mid

Answer

Unsafe context enables pointer operations and direct memory access for performance-critical scenarios.

Quick Summary: The unsafe keyword enables pointers and direct memory operations — things C# normally disallows. Used for performance-critical scenarios like native library interop, image processing, or high-speed buffers. Requires /unsafe compiler flag. Outside these niche cases, managed code is always safer.
Q14:

What are custom exceptions?

Mid

Answer

Custom exceptions are user-defined exception classes representing application-specific errors.

Quick Summary: Custom exceptions are your own exception classes that extend Exception. They let you signal application-specific errors with meaningful names and carry extra context. OrderNotFoundException is clearer than a generic Exception. By convention, exception class names always end with Exception.
Q15:

What is the purpose of the nameof operator?

Mid

Answer

The nameof operator returns the string name of variables, properties, or methods.

It eliminates magic strings and improves refactoring safety.

Quick Summary: nameof returns the string name of a variable, property, or method at compile time. Instead of hardcoding "PropertyName" (breaks silently on rename), use nameof(PropertyName). Common in INotifyPropertyChanged, argument validation, and logging. Fully refactor-safe.
Q16:

What is method shadowing?

Mid

Answer

Method shadowing occurs when a derived class hides a method from the base class using the new keyword.

Quick Summary: Shadowing is when a derived class defines a method with the same signature as the base class using the new keyword — not override. Call via a derived reference and you get the derived version; call via a base reference and you get the base version. Usually a code smell; prefer override.
Q17:

What is the difference between synchronous and asynchronous execution?

Mid

Answer

Synchronous: Blocks the calling thread until the operation completes.

Asynchronous: Continues execution without blocking, offering better scalability and responsiveness.

Quick Summary: Synchronous code runs step by step, blocking the thread until each operation finishes — simple but wasteful for I/O. Async with await frees the thread while waiting and resumes later. On a web server, async lets one thread handle many concurrent requests instead of sitting idle waiting for DB responses.
Q18:

What is a memory leak in .NET?

Mid

Answer

A memory leak occurs when unused objects remain referenced, preventing garbage collection and increasing memory usage.

Quick Summary: Even with GC, memory leaks happen in .NET when objects stay referenced longer than needed. Common causes: unsubscribed event handlers, static collections holding old references, caches that never clear. Use memory profilers (dotMemory, VS Profiler) to find them. Always unsubscribe events when done.
Q19:

What is the purpose of StringBuilder?

Mid

Answer

StringBuilder efficiently manages dynamic string modifications without creating multiple intermediate immutable strings.

Quick Summary: Strings in C# are immutable — every + creates a new string object. Concatenating in a loop creates thousands of temporary strings. StringBuilder is a mutable buffer that appends in-place without intermediary objects. Use it when building strings in loops. For two or three concatenations, + is perfectly fine.
Q20:

What is the difference between equality operator and reference equality?

Mid

Answer

Equality operator: Checks logical equality when overridden.

Reference equality: Checks if two references point to the same object instance.

Quick Summary: For reference types, == by default checks if two variables point to the same object in memory. object.ReferenceEquals() always does this. But classes can override == and Equals() to compare by content. String does exactly this — two different string objects with the same text are ==.
Q21:

What is the difference between value-type semantics and reference-type semantics in C#?

Mid

Answer

Value types store their actual data directly on the stack (or inline within other objects). Assigning one value type to another copies all data.

Reference types store references to objects on the heap. Assigning one reference variable to another makes both point to the same object.

This difference impacts memory layout, performance, assignment behavior, parameter passing, and garbage collection.

Quick Summary: Value-type semantics: copying means two fully independent values — change one, the other is unaffected. Reference-type semantics: copying means both variables point to the same object — change through one and both see it. Understanding this distinction prevents a huge category of subtle bugs.
Q22:

What is boxing and unboxing in C#? Why does it affect performance?

Mid

Answer

Boxing converts a value type into an object by wrapping it inside a heap-allocated reference type.

Unboxing extracts the value type back from the object.

Boxing and unboxing are slow due to heap allocation, GC pressure, and runtime type-checking.

Quick Summary: Boxing wraps a value type (like int) in a heap-allocated object so it can be treated as object. Unboxing extracts it back. The problem: boxing allocates heap memory and adds GC pressure. In tight loops or large collections, this adds up fast. Use generics (List not ArrayList) to avoid boxing.
Q23:

What is the purpose of the IDisposable interface? When should you implement it?

Mid

Answer

IDisposable defines a contract for releasing unmanaged resources such as file handles, sockets, and database connections.

Implement IDisposable when your class owns unmanaged resources that the garbage collector cannot free automatically.

Quick Summary: IDisposable has one method: Dispose(). Implement it when your class holds unmanaged resources (file handles, DB connections, sockets) or subscribes to events. Wrap in using or call explicitly. The GC will never call Dispose automatically — that is your responsibility.
Q24:

What are generics in C#, and why are they important?

Mid

Answer

Generics enable type-safe classes and methods that work with any data type.

They eliminate casting, reduce runtime errors, prevent boxing, and improve performance.

Quick Summary: Generics let you write one implementation that works safely for multiple types. Dictionary works for any combination without casting or boxing. Compile-time type checking catches errors early. Before generics, object-based collections were the only option — error-prone and slow.
Q25:

What is the difference between const and readonly?

Mid

Answer

const: Compile-time constant; must be assigned at declaration.

readonly: Runtime constant; can be assigned at declaration or inside a constructor.

Readonly avoids versioning issues because its value is not embedded into IL.

Quick Summary: const is a compile-time constant — the value is baked into compiled code, must be a primitive or string, implicitly static. readonly is a runtime constant — set at declaration or in the constructor. Prefer readonly for complex values or when the value depends on runtime data.
Q26:

What is the difference between overloading and overriding in C#?

Mid

Answer

Overloading: Same method name, different parameters; resolved at compile time.

Overriding: Derived class redefines base class virtual methods; resolved at runtime.

Quick Summary: Overloading: same method name, different parameters — resolved at compile time based on argument types. Overriding: derived class replaces a virtual base method — resolved at runtime based on the actual object type. Overloading is a compile-time feature; overriding is a runtime one.
Q27:

What is the purpose of the GC (Garbage Collector) in .NET? How does it work?

Mid

Answer

The Garbage Collector (GC) frees unused heap objects automatically.

It uses generations (Gen0, Gen1, Gen2) to optimize collection of short-lived and long-lived objects.

The GC pauses execution, removes unreachable objects, and compacts memory.

Quick Summary: The GC automatically reclaims heap memory using a generational model. Gen0 holds new objects and is collected most often. Gen1 holds objects that survived one collection. Gen2 holds long-lived objects and is collected rarely. Most objects die young — this model exploits that to stay efficient.
Q28:

What is the difference between synchronous and asynchronous execution in C#?

Mid

Answer

Synchronous: Blocks the calling thread until completion.

Asynchronous: Frees the thread and allows other operations to run concurrently.

Async-await uses Tasks and compiler-generated state machines.

Quick Summary: Sync blocks the current thread until completion — simple but wasteful for I/O bound work. Async with await frees the thread during the wait using compiler-generated state machines. On web servers, async means one thread can handle many concurrent requests instead of sitting idle.
Q29:

What are thread-safe operations, and why are they important?

Mid

Answer

Thread-safe operations ensure consistent behavior when accessed concurrently by multiple threads.

They prevent race conditions, deadlocks, inconsistent states, and crashes.

Quick Summary: Thread-safe means multiple threads can access the same data simultaneously without corrupting it. Without it, two threads might read-modify-write a value at the same time and one update is lost. Use lock, Interlocked operations, ConcurrentDictionary, or immutable types to achieve thread safety.
Q30:

What is immutability? Why is it recommended in multi-threaded scenarios?

Mid

Answer

Immutability means an object's state cannot change after creation.

It avoids the need for locks and prevents corruption in multi-threaded environments.

Quick Summary: An immutable object never changes after creation. Since threads can only read it, no locks are needed — no race conditions possible. C# supports this with readonly fields, record types, and init-only properties. Immutability makes concurrent code dramatically simpler and safer.
Q31:

What is the difference between static constructor and instance constructor?

Mid

Answer

Static constructor: Initializes static members once per type.

Instance constructor: Initializes object instances and runs per object.

Quick Summary: An instance constructor runs every time you create an object with new — initializes that specific instance. A static constructor runs once — the first time the class is accessed — to set up static members shared across all instances. Neither can be called manually; both run automatically.
Q32:

What is a delegate chain (multicast delegate)?

Mid

Answer

A delegate chain is a list of methods attached to a single delegate.

Invoking the delegate executes all attached methods in sequence.

Quick Summary: A multicast delegate holds references to multiple methods. Invoking it runs all attached methods in sequence. Use += to attach and -= to detach. Events are built on multicast delegates. If any method throws an exception, subsequent methods in the chain will not run.
Q33:

What is an event handler in C#, technically?

Mid

Answer

An event handler is a delegate following the .NET event pattern.

Events encapsulate delegates and restrict invocation to the declaring class.

Quick Summary: An event handler is a method matching the event delegate signature — typically void Handler(object sender, EventArgs e). Register with event += Handler, called when the event fires. EventHandler is the standard .NET pattern for typed event data.
Q34:

What is reflection emit?

Mid

Answer

Reflection Emit enables runtime creation of types, methods, and IL.

Used in ORMs, serializers, proxies, and dynamic frameworks.

Quick Summary: Reflection Emit enables creating types, methods, and IL code at runtime dynamically. Used in ORMs, serializers, proxy generators, and dynamic frameworks. Extremely powerful but complex and slow — only reach for it when no other approach works.
Q35:

What is the purpose of strong naming assemblies?

Mid

Answer

Strong naming uses a cryptographic key pair to sign assemblies.

It ensures authenticity, prevents tampering, and enables GAC deployment.

Quick Summary: Strong naming signs an assembly with a cryptographic key pair. It ensures authenticity, prevents tampering, and enables deployment to the Global Assembly Cache (GAC). Required for assemblies shared across multiple applications on the same machine.
Q36:

What is method binding?

Mid

Answer

Method binding connects method calls to implementations.

Early binding = compile time; late binding = runtime.

Quick Summary: Method binding connects a method call to its implementation. Early binding happens at compile time — the compiler knows exactly which method to call. Late binding happens at runtime — used with virtual methods, dynamic, and reflection. Early binding is faster and safer.
Q37:

What are attributes in C#, and how do they work?

Mid

Answer

Attributes add metadata to program elements.

Frameworks read attributes to enforce policies, control behavior, or generate code.

Quick Summary: Attributes add metadata to program elements — classes, methods, properties, parameters. Frameworks read them at runtime via reflection to enforce policies or generate behavior. You can create custom attributes by extending the Attribute base class.
Q38:

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

Mid

Answer

Struct: Value type, stack-allocated, lightweight.

Class: Reference type, heap-allocated, supports inheritance and advanced OOP.

Quick Summary: Struct is a value type — stack-allocated, lightweight, copied on assignment, no inheritance. Class is a reference type — heap-allocated, supports inheritance and full OOP. Use struct for small, immutable, data-focused types like Point or Color. Use class for everything else.
Q39:

What is tail recursion?

Mid

Answer

Tail recursion occurs when the final operation of a method is a recursive call.

Allows optimization of stack usage and prevents stack overflow.

Quick Summary: Tail recursion is when the very last thing a method does is call itself recursively. Some compilers optimize this into a loop to avoid growing the call stack. C# does not guarantee tail call optimization, but understanding it matters for writing stack-safe recursive algorithms.
Q40:

What are anonymous methods?

Mid

Answer

Anonymous methods allow defining inline method bodies.

They support closures and are often used in event handling.

Quick Summary: Anonymous methods let you define an inline method body without naming it: button.Click += delegate(object s, EventArgs e) { ... }. They support closures — capturing variables from the enclosing scope. Lambda expressions are the modern, cleaner syntax for the same idea.

Curated Sets for C#

No curated sets yet. Group questions into collections from the admin panel to feature them here.

Ready to level up? Start Practice