Press "Enter" to skip to content

Tag: C# Design Patterns

C# Interview Questions and Answers (2025)

I’m preparing for interviewing and want to get ready for the inevitable C# trivia questions that will inevitably come up. Here is my study sheet for anyone else who may also be going through interviews for a C# programmer position.

If anything looks wrong, unclear, or is missing, please leave a comment.

General C# Questions

What is the difference between an abstract class and an interface?

  • An abstract class
    • Cannot be instantiated directly
    • Used as a base for classes that can be instantiated
    • Can have private, protected, or public fields, properties, functions, constructors
    • Only allows single inheritance
  • An interface
    • Defines the public methods, properties, and/or events that must be implemented in classes that implement the interface
    • Doesn’t include fields or constructors
    • Classes can implement multiple interfaces
    • In C# 8.0, can have default implementation for methods

 

What is the difference between the stack and the heap?

  • The stack
    • Stores value types: int, struct, bool
    • Fast access
    • Can store 1 MB per thread (hence, the ability to overflow)
    • Stores values with limited lifetimes (scope-bound)
  • The heap
    • Stores reference types: class, string, arrays
    • Slower, due to memory allocation and garbage collection
    • Limited by available system memory
    • Stores values with potentially long lifetimes

 

What is the difference between IEnumerable and IQueryable?

  • IEnumerable
    • From System.Collections.Generic
    • Eager evaluation
    • Loads all value into memory, then enumerates over them
    • Better for small datasets
  • IQueryable
    • From System.Linq
    • Lazy evaluation
    • Builds an expression tree that is deferred until enumeration, like .ToList()
    • Better for large datasets

 

Explain the difference between ref and out parameters in C#.

  • ref
    • Must be initialized before passing into method
    • Can be read or modified inside the method (but does not need to be)
  • out
    • Does not need to be initialized before passing into method
    • Must be assigned a value before method execution ends

 

What is boxing and unboxing in C#? Provide an example.

  • Boxing
    • Converting a value type (e.g., int, struct) to a reference type (e.g., object or an interface type).
    • Occurs implicitly when a value type is assigned to a variable of type object or an interface.
    • Allocates memory on the heap and copies the value, creating a reference type instance.
    • Can hurt performance due to heap allocation and garbage collection overhead.
  • Unboxing
    • Converting a reference type (e.g., object) back to a value type.
    • Requires an explicit cast to the original value type.
    • Throws an InvalidCastException if the boxed type doesn’t match the unboxed type.
    • Has performance overhead due to type checking and memory access.
  • NOTES
    • Best to use generics (List<T>, etc.), for performance

 

What is the purpose of the using statement in C#?

  • Different from the “using” directive, which is used to simplify using code in a class from other namespaces
  • Use this when instantiating an object that implements IDisposable
  • Automatically calls the Dispose method when the object goes out of scope (reaches the end of the code block/method)
  • Use for things like SqlConnection, SqlCommand, FileStream, Stream

 

What is the difference between String and StringBuilder? When would you use each?

  • String
    • An immutable (unchangeable) reference type
    • If a string is changed, a new string object is created on the heap
    • Best used when you won’t need to change much
  • StringBuilder
    • Mutable class
    • Modifications happen to the same instance. No new object created for changes
    • Best used when you may need to make many changes to the value

 

What are generics in C#? How do they improve performance?

  • They are placeholders for types in code that can be used for several different datatypes
  • Allow code reusability, without needing to box/unbox values

 

Explain the var keyword in C#. How is it different from dynamic?

  • var
    • Syntactical “sugar”. Actual type is used during compile time.
    • Once it is inferred (by assigning a value to the variable), the type cannot be changed
    • Must be assigned a value when it is defined
    • Cannot be used for fields, parameters, or return types
  • dynamic
    • Type is determined at runtime
    • Can be reassigned to a value of a different datatype
    • No Intellisense
    • Runtime resolution is generally slower than compile-time
    • Often used for COM interop or calling dynamic APIs

 

Object-Oriented Programming (OOP)

What is SOLID?

  • Single responsibility principle
    • A class should only have one responsibility
    • Makes code easier to maintain as classes are generally smaller and changes don’t affect (and possibly cause problems with) other logic
  • Open-close principle
    • Classes should be open for extension, but closed for modification
    • Once a class works, you can “close” it for modification and put new changes in a different (possibly child) class.
  • Liskov substitution principle
    • Functions that accept a value that is a parent class should also accept a child of that class
  • Interface segregation principle
    • Clients should not be forced to depend on interfaces they do not use
    • For example, if a class has 20 methods, and is being passed into a method that only needs to use one of them, you may want to have the class implement an interface that only requires that one method, and set the datatype for the method’s parameter to the interface, instead of the class.
  • Dependency inversion principle
    • Instead of a class instantiating a new object, that object should be passed into the class.
    • Allows the ability to pass in an object that does something else (for example, reading data from a different type of database)

 

What is the difference between method overloading and method overriding?

  • Method overloading
    • Multiple methods in a class can have the same name, but different parameters
    • Return types can be different, but that cannot be the only difference (the method also needs different parameters)
    • Resolved at compile-time
  • Method overriding
    • A child class has a specific implementation of a method that is also in the parent class
    • The method in the child class must have the same name, parameters, and return type as the method in the parent class
    • Parent method must be marked “virtual” or “abstract”
    • Child method must be marked “override”
    • Child method can call parent method with “base.MethodName();”
    • Resolved at runtime

 

What is a sealed class? Why would you use it?

  • A sealed class cannot be inherited by any other class
  • Used if you want to ensure no other programmer makes a child class that could implement other logic
  • Can slightly improve performance

 

What is the difference between virtual and abstract methods?

  • Virtual methods
    • Used in a base class
    • Has default logic to use
    • Can be overridden in child class
  • Abstract methods
    • Used in a base class
    • Base class must be an abstract class
    • Does not have default logic, only the method signature
    • Must be overridden in child class

 

What is a partial class in C#? When would you use it?

  • Partial classes allow you to split code for a single class across multiple files
  • All parts must:
    • Bee in the same namespace
    • Include the “partial” keyword
    • Have the same access level (public, private, etc.)
  • During compile time, they are merged into the same class
  • Generally, if you are using partial classes (for other than the typical separation for things like .cs and xaml.cs files), it’s probably an indication the class is doing too much.

 

Explain the concept of encapsulation and give an example

  • Encapsulation is managing private data by only allowing access through something with more visibility (property setter/getter, method, etc.)
  • This controlled access lets you do things like validate, return defaults, lazy-load, etc.

 

What is a static class in C#? When would you use it?

  • Generally used for helper methods or utilities (like a logger)
  • Can only have static members (properties, fields, methods, etc.)
  • It cannot be instantiated
  • Cannot be used as a base class
  • Sealed by default

 

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

  • Struct
    • Generally used to hold a small amount of data (properties), like X/Y coordinates, or datetimes
    • Value type (stored on stack)
    • Variable of this datatype cannot be null, unless using Nullable<T> or struct?
    • Cannot have a derived/child struct
    • Cannot be abstract or sealed
  • Class
    • Generally used to hold a larger amount of data, although classes can have only a few properties
    • Reference type (stored on heap)
    • Variable of this datatype can be null
    • Can be abstract or sealed
    • Can have a derived/child class

 

Memory Management and Garbage Collection

How does the Garbage Collector work in .NET?

  • Allocation: Objects are allocated space on the heap
  • Mark phase: When garbage collection runs, it marks objects that are no longer reachable by the code
  • Sweep phase: Garbage collection reclaims space from unreachable objects. The remaining objects are compacted, to reduce memory fragmentation, and pointers are updated for the objects that were moved.
  • Generational collection: The garbage collection uses three generations (0, 1, and 2). When an object is first created, it is Gen 0. When an object remains after a garbage collection, it is moved up to the next generation. Garbage collection is run on Gen 0 frequently, Gen 1 less often, and Gen 2 rarely. So, objects that survive multiple garbage collections are less likely to be checked in the future.
  • Large Object Heap (LOH): Objects larger than 85,000 bytes are allocated in the LOH, which is collected less often and only compacted in special situations, to prevent costly memory moves.
  • There is Workstation and Server Garbage Collection, with Server GC optimized for multi-core environments.
  • Developers can manually call garbage collection, using GC.Collect(), but that is rarely needed.

 

What is the difference between a managed resource and an unmanaged resource?

  • Managed resource
    • Objects allocated and managed by the .NET CLR, like strings, collections, etc.
    • Memory is automatically reclaimed by garbage collection
  • Unmanaged resource
    • Resources outside the CLR’s control, like file handles, database connections, and network sockets.
    • Memory is reclaimed by calling the Dispose() method

 

What is the difference between Finalize and Dispose in C#?

Both are used to clean up resources that are no longer needed.

  • Finalize
    • Protected fallback method to clean up unmanaged resources if Dispose isn’t called
    • Invoked by the garbage collector (which can slow down garbage collection)
  • Dispose
    • Part of the IDisposable interface
    • Explicitly called by the developer to clean up unmanaged, and possibly managed, resources

 

What is the IDisposable interface? How is it used?

  • This is used to manage cleanup of unmanaged resources (file handles, database connections, etc.)
  • Requires the object has a Dispose() method to release unmanaged resources (via their Close() or Release() methods) and possibly managed resources.
  • Can be used by explicitly calling the Dispose() method, or when exiting a code block where the object was instantiated with a “using” statement. Dispose is run even if an exception occurs within the code block (when the object was instantiated with “using”).
  • If a class has managed and unmanaged resources, the pattern is to have the Dispose() method call a Dispose(bool disposing) method, to prevent running the disposal logic twice.
  • Dispose() method must be idempotent (able to be called multiple times, without causing a negative side effect)

 

What are weak references in C#? When would you use them?

Weak references are used when you don’t want to prevent possible garbage collection of an object.

A strong reference would identify to the garbage collector that the object is still needed, and prevent the object from being released from memory.

These may be used for things like caching large amounts of data (which can be refreshed if the object holding the data was garbage collected) or event listeners that may unintentionally keep an object in memory when it is no longer needed.

 

Multithreading and Asynchronous Programming

What is the difference between Task and Thread in C#?

  • Task
    • An asynchronous operation that can run at the same as other code running in the application
    • May, or may not, create a separate thread
    • The rest of the code is not blocked, waiting for this code to execute
  • Thread
    • Low-level construct that the developer can have more control over
    • Can be more difficult to manage, due to the developer needing to control lifecycle and synchronization

 

Explain async and await in C#. Provide an example.

  • Async
    • Keyword to indicate that a method should run asynchronously
    • An async method returns Task or Task<T> (for methods with a return value) or void for event handlers
  • Await
    • Keyword applied to a Task, to yield control back to the caller until the Task has completed, allowing other operations to continue on the calling thread
    • For example, this lets the UI thread continue handling things like moving or resizing the window while the long-running Task is running.

 

What is the purpose of the lock keyword in C#?

The lock keyword is used to ensure that only one thread at a time can access a shared resource. This prevents potential race conditions (one thread accesses a resource before the other thread does what it needs to do with the resource) and possible data corruption.

 

What is a deadlock? How can you avoid it in C#?

A deadlock is when two threads need to access that each other thread has locked, preventing each thread from being able to continue.

To prevent them, use thread-safe datatypes, like ConcurrentDictionary, or use async/await with Task instead of manual thread management.

 

What is the difference between ConfigureAwait(true) and ConfigureAwait(false)?

  • ConfigureAwait(true) (default): The code after await runs on the original context, like the UI thread in a desktop app or the request context in ASP.NET. Use this when you need to update UI or access context-specific resources.
  • ConfigureAwait(false): The code after await runs on a thread pool thread, not the original context. This is faster and used for tasks like file I/O or calculations that don’t need the original context.

 

What are cancellation tokens in C#? How are they used?

Cancellation tokens are similar to events/exceptions. They are passed to asynchronous functions to allow for graceful cancellation of long-running tasks.

When a cancellation is triggered, it can stop execution of the task and let the calling method know the task did not complete and was cancelled instead.

 

LINQ and Data Access

What is LINQ? Explain the difference between LINQ to Objects and LINQ to SQL.

LINQ (Language Integrated Query) lets developers manipulate data in a type-safe manner.

  • LINQ to Objects
    • Works with in-memory collections that implement IEnumerable, like lists or arrays
    • Allows you to filter, sort, and transform data in these collections
  • LINQ to SQL
    • Works with relational databases, mapping database tables to .NET classes
    • Requires a database connection and potentially query optimization

 

What is deferred execution in LINQ? Provide an example.

When you filter, sort, or transform a collection, the logic is not executed until you materialize it (for example, with .ToList()) or when additional code iterates through it (for example, in a foreach loop).

 

What is a potential problem, and solution, for using unmaterialized LINQ for a variable, field, or property?

If you don’t materialize a LINQ query, and the underlying collection changes, you can get different results when you execute logic against the unmaterialized LINQ query.

 

How would you optimize a LINQ query for performance?

  • Apply Where() clauses early in LINQ query chains, to reduce the number of objects needed to run subsequent LINQ functions on.
  • Materialize the query results with ToList() or ToArray() if you need to have following code run through the results multiple times, to prevent re-executing the query each time.
  • Use functions that can short-circuit. For example, use Any() (which stops processing once it encounters the first object that meets the condition) instead of “Count() > 0” (which would run through every object in the collection).

 

What is Entity Framework? Explain the difference between Code-First and Database-First approaches.

Entity Framework is an Object-Relational Mapping (ORM) framework to simplify connecting to databases.

  • Code-first
    • Create model classes in code, then generate the database schema from those classes
  • Database-first
    • Create database tables first, then generate the model classes from those tables

 

Exception Handling

What is the purpose of the try, catch, and finally blocks?

These blocks are used to handle exceptions gracefully

  • Try block
    • The code that is expected to run, but may possibly have an exception
  • Catch block
    • Code that is run if/when an exception occurs
    • May include logging, retry logic, raising the exception to the calling code, etc.
  • Finally block
    • Code that is run in all cases, regardless of whether an exception occurred or the try block completed successfully

 

What are the differences between throw, throw ex, and throw new Exception, when used in a catch block?

  • throw
    • Rethrows the original exception to the calling code
    • Retrains the full stack trace and exception details
    • The preferred method
  • throw ex
    • Rethrows the original exception
    • Resets the stack trace to the line of the “throw ex” statement
  • throw new Exception
    • Creates and throws a completely new exception
    • Resets the stack trace to the line of the “throw new Exception” statement
    • Loses the original exception information, unless you explicitly set it in the new Exception (generally, by setting the new Exception’s InnerException to the original Exception)

 

What is a custom exception in C#? How do you create one?

This is a developer-created Exception that may be used to identify an application-specific error and possibly contain additional information through additional properties.

You can create a custom exception by creating a new class that inherits from the built-in Exception, or ApplicationException, class.

 

Advanced C# Features

What are delegates in C#? How are they different from events?

  • Delegates
    • Type-safe pointers that allow methods to be passed as parameters or assigned to a variable
    • Can be invoked by any class with access/visibility to them
  • Events
    • A type of delegate used to implement the publisher-subscriber pattern
    • Can only be raised by the class that defines them, ensuring encapsulation

 

What is the purpose of the yield keyword in C#?

When used inside a method that returns a datatype that is IEnumerable or IEnumerator (or their generic versions), lets the method return one value, until the next time the calling method attempts to get the next value.

This may be useful if the method could produce an infinite (or extremely long) sequence, like all prime numbers.

 

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

  • A constant is assigned its value when it is declared and can never be changed
  • A readonly field can be assigned a value when it is declared and it can be assigned a value in the constructor. Once the object has been instantiated (the constructor has completed), the field cannot be assigned another value.

 

What are extension methods in C#? Provide an example.

  • Extension methods let you add new methods to a datatype
  • Must be a static method in a static class
  • First parameter is prefixed with “this”, for the object that the extension method is being used for.
  • Can make the code more readable, by naming the extension method something that sounds like a natural language word or phrase
  • As an example, you could create a ToTitleCase() extension method that returns a string with the first letter of each word capitalized, similar to the built-in ToUpper() and ToLower() methods available on strings.

 

What is dependency injection in C#? How is it implemented in .NET?

Dependency injection is a design pattern to reduce coupling by passing dependent objects into a class/method, instead of the class instantiating them itself.

This makes code more modular, maintainable, and testable by letting dependencies be swapped or mocked easily.

.NET has a DI framework available in the Microsoft.Extensions.DependencyInjection NuGet package.

Classes to be injected are defined in the Program.cs or Startup.cs files. The dependent classes can be registered for different lifetimes, via AddScoped, AddTransient, and AddSingleton.

In the constructors of classes, if a parameter datatype was defined in the Program.cs or Startup.cs, the dependency injection framework will create (or reuse) the instance of the object needed.

  • Transient: A new instance is created each time it is needed (for each object that has its datatype in its constructor)
  • Scoped: Creates, or reuses, an object within a specific scope. For example, an HTTP request.
  • Singleton: A single instance of the object is created for the entire application lifetime

 

What is the purpose of the record type introduced in C# 9?

The record type is designed to hold immutable data. It enables C# to be more like a functional language, which can eliminate errors that can arise from unintended state issues with multi-threaded code.

  • Immutable Data Models: Records are immutable by default, ensuring data consistency and thread safety, which is ideal for representing data transfer objects (DTOs) or value-like objects.
  • Value-Based Equality: Records automatically implement value equality, comparing all properties for equality rather than reference equality, simplifying comparisons.
  • Concise Syntax: Records reduce boilerplate code with a compact syntax for defining properties and implementing common functionality like equality, hashing, and string representation.
  • Simplified Data Manipulation: Features like with expressions enable easy creation of modified copies of records (non-destructive mutation).

 

What are nullable reference types in C# 8? How do they help prevent null reference exceptions?

By default, variables, field, properties that use a reference datatype cannot be null. So, code that could potentially have a null-reference exception can be detected during compile-time, instead of at runtime. This lets the developer write code to handle (or explicitly allow) potential null values.

This also makes the intention of the code clearer during maintenance and support.

Leave a Comment