.NET turned 25 in 2025 and is now in its sixth unified release as .NET 10 LTS. The platform spans web, cloud, mobile, desktop, and high-performance services, which is why .NET interviews cover so much ground.

This guide collects 150 .NET interview questions for junior through senior developers. The questions cover C#, ASP.NET Core, Entity Framework Core, distributed systems, and Azure, with answers for the current .NET 10 / C# 14 release. Each tier maps to the depth a candidate at that level should reach in a real screening conversation.

 

.NET Interview Questions for Junior Developers

Junior .NET interviews target candidates with roughly 0–2 years of experience, typically freshers or developers in their first commercial role. The screen focuses on foundational language and platform knowledge. Can the candidate explain what the CLR does and why value types behave differently from reference types? Can they articulate when async beats raw threading? The questions below cover the topics a hiring manager should expect a junior to handle in a first technical conversation.

Junior .NET developer skills

General .NET Interview Questions

1. What are the main principles of OOP (Object-Oriented Programming)?

Encapsulation involves bundling data (properties) and methods into a single unit called a class. Encapsulation helps hide the internal implementation details of an object and provides a well-defined interface for interacting with the object.

Abstraction focuses on the essential features of an object, hiding the unnecessary details. It allows you to create abstract classes and interfaces that define a contract without specifying the implementation details.

Inheritance allows a derived class to inherit properties and methods from a base class. It promotes code reuse and helps create hierarchical relationships between classes.

Polymorphism enables objects of different classes to be treated as objects of a common superclass. It allows you to write more generic and flexible code that can work with objects of different types.

 

2. What are inheritance, encapsulation, abstraction, and polymorphism? Provide examples (preferably from your own experience). From which class are all classes in .NET implicitly inherited? Is multiple inheritance allowed in C#?

Inheritance is the ability of a derived class to inherit properties and methods from a base class. Encapsulation is the idea of bundling data and methods into a single unit (class) and hiding the internal implementation details.

Abstraction focuses on the essential features of an object, hiding the non-essential details. Polymorphism allows objects of different classes to be treated as objects of a common superclass.

In .NET, all classes implicitly inherit from the Object class, which is the base class for all .NET classes. Multiple inheritance is not allowed in C# but can be achieved through interfaces.

 

3. What is recursion?

Recursion is a programming technique where a function calls itself to solve a problem. It involves breaking down a problem into smaller, similar subproblems until a base case is reached. Recursive functions are often used to solve problems that can be defined in terms of smaller instances of the same problem, such as traversing tree-like data structures, calculating factorials, or generating Fibonacci sequences.

 

4. What is a lambda expression?

A lambda expression is an anonymous function that can be used as a method argument or to initialize a variable. This function concisely represents a method, allowing you to write more readable and expressive code. Lambda expressions are commonly used in LINQ queries and various event handlers.

 

5. What is parallel programming (multithreading), and its purpose? Which classes are used?

Parallel programming, or multithreading, is the ability of a system to support multiple threads of execution simultaneously. It improves performance by utilizing multiple processors or cores, allowing the application to perform multiple tasks concurrently. In .NET, classes like Task, Thread, and the Task Parallel Library (TPL) are commonly used for parallel programming.

 

6. What is JSON?

JSON (JavaScript Object Notation) is a text-based data interchange format that machines can parse and generate easily. JSON is often used as an alternative to XML to transmit data between a server and web application.

 

7. What is your understanding of REST?

REST (Representational State Transfer) is an architectural style for building web services that use HTTP methods (GET, POST, PUT, DELETE) to perform CRUD (Create, Read, Update, Delete) operations on resources. REST APIs offer a structured way to access and manage web services. Clients can interact with these services using standard rules and protocols.

 

8. Explain the SPA (Single Page Application) concept.

Single Page Applications (SPAs) concept is a web application model that initially loads a single HTML page. As users interact with the app, content updates dynamically without reloading the entire page.

 

9. Which GoF (Gang of Four) design patterns have you used?

Some commonly used GoF (Gang of Four) design patterns include:

  • Singleton ensures a class has only one instance and provides a global point of access to it.
  • Factory defines an interface for creating objects but lets subclasses decide which class to instantiate.
  • Adapter converts the interface of a class into another interface the client expects.
  • Observer defines a one-to-many dependency between objects. So that when one object changes state, all its dependents are notified and updated automatically.
  • Strategy defines a family of algorithms, encapsulates each one, and makes them interchangeable.

10. What is the difference between the GET and POST HTTP methods?

GET requests retrieve data from the server, and the requested data is included in the URL.
POST requests send data to the server, and the data is included in the request body.

 

11. What problem does Docker solve? What are its pros and cons?

Docker solves the “works on my machine” problem by packaging an application with its dependencies into a standardized unit called a container. This container ensures that the application will run consistently across different environments. Some of the key benefits of Docker include:

  • Consistent Environment: Docker containers provide a consistent, isolated runtime environment, ensuring the application behaves the same way across different systems.
  • Faster Deployment: Docker's containerization and image-based deployment model make it easier and faster to deploy applications.
  • Better Resource Utilization: Docker's efficient use of system resources, such as CPU and memory, can lead to better utilization of the underlying infrastructure.

The main downsides of Docker include increased complexity, potential security concerns, and the risk of vendor lock-in.

 

Exception Handling

12. What is an Exception?

An Exception is an event that occurs during the execution of a program that disrupts the normal flow of the program’s instructions. Exceptions handle unexpected situations in a program, such as division by zero or invalid user input.

 

13. What are the purposes of try, catch, and finally blocks? In what case can the finally block not be executed?

The try block encloses code that might throw an exception.

The catch block handles the exception and provides appropriate error-handling logic.

The final block executes code that should run regardless of whether an exception is thrown or not.

The finally block might not execute if the process is terminated, such as when Environment.FailFast() is called, or the process is abruptly shut down.

 

14. What is a call stack? What are the key keywords you know?

The call stack is a stack data structure that stores information about the active subroutines of a computer program. It keeps track of the functions or methods that have been called and the order in which they were called. Keywords related to the call stack include try, catch, throw, and finally.

 

.NET Core and ASP.NET Interview Questions

15. What is ASP.NET?

ASP.NET is a web application framework developed by Microsoft for building dynamic websites, web applications, and web services. It provides a programming model and a set of tools and libraries for developing web applications using .NET.

 

16. What types of Action filters exist?

The main types of Action filters in ASP.NET MVC are:

Authorization Filters: These are used to control access to actions based on authorization rules.

Action Filters: Used to perform pre-processing or post-processing logic for actions.

Result Filters: Used to modify the result of an action.

Exception Filters: Used to handle exceptions that occur during the execution of an action.

 

17. What is a Web Service?

A Web Service is a software system designed to support interoperable machine-to-machine interaction over a network. Standard protocols like SOAP, REST are typically used.

 

18. What is CLR (Common Language Runtime)?

CLR (Common Language Runtime) is the execution engine of the .NET Framework. CLR provides a runtime environment for executing .NET applications, handling memory management, code execution, and other low-level details.

 

19. What is Garbage Collector at a basic level?

Garbage Collector is a mechanism in .NET that automatically reclaims memory occupied by objects no longer used by the application. This mechanism scans the memory (managed heap) to find unused objects and reclaim their space for future use.

 

20. What is a delegate?

A delegate is a type that represents a method with a particular signature. Delegates are used to pass methods as arguments to other methods or store methods in variables, enabling function pointers in C#.

 

21. What are records in C#, and when should you use them?

Records are a reference type (record class) or value type (record struct) introduced in C# 9 and expanded in C# 10. They give you a concise syntax for immutable data carriers without the boilerplate of writing constructors, properties, equality members, and ToString overrides by hand.

A typical declaration looks like public record Customer(string Name, string Email);. The compiler generates the constructor, property getters, value-based equality, deconstruction support, and a readable ToString. The with expression creates a copy with selected properties changed: var renamed = customer with { Name = “New Name” };.

Two Customer instances compare equal when their property values match. The reference identity does not affect the comparison, which makes records a natural fit for DTOs, API request and response shapes, configuration objects, and any data carrier where identity flows from the contents.

Use a regular class when you need mutable state or behavior-heavy types. A class is also the right choice when reference equality is what you care about.

 

22. What is LINQ, and what is it used for? Provide a few examples of LINQ usage.

LINQ (Language Integrated Query) is a set of extensions to the .NET Framework that provide a generic way to query and transform data from various data sources. Examples of LINQ usage include querying collections, accessing databases using LINQ to Entities, and transforming XML data.

 

23. What is a namespace, and why is it needed?

A namespace is a way to organize and scope classes, interfaces, and other types in .NET. Namespaces help prevent naming collisions and make the code more maintainable by grouping related types together.

 

Data Types, Collections, and Data Structures

24. What data types do you know?

The main data types in C# can be divided into value and reference types.

  • Value types: Include the primitive data types (e.g., int, float, bool, char, byte) and user-defined structs. Store their data directly in memory.
  • Reference types: Include classes, interfaces, delegates, and arrays. Store a reference (pointer) to the actual data, which is stored on the managed heap.

25. What primitive types do you know?

The primitive data types in C# include:

Signed integer types: sbyte, short, int, long
Unsigned integer types: byte, ushort, uint, ulong
Floating-point types: float, double
Decimal type: decimal
Boolean type: bool
Character type: char

 

26. What is a Nullable type?

A Nullable type is a value type that can also have a null value. It’s denoted with the ? suffix, e.g., int?. Nullable types are useful when you need to represent the absence of a value. Such as when working with databases where a column may have a null value.

 

27. What is a value type, and what is a reference type? What of these is a class, and what is a struct? In which area of memory are they stored?

Value types store their data directly in memory, while reference types store a reference (pointer) to the data. Classes are reference types, while structs are value types.
Value types are stored on the stack, while reference types are stored on the managed heap.

 

28. How do value and reference types differ? Is String a reference or a value type?

Value types are copied by value, creating a copy of the actual data.
Reference types are copied by reference, creating a copy of the reference (pointer).
String is a reference type in C#, not a value type.

 

29. What is the difference between StringBuilder and String?

StringBuilder is a mutable string type, meaning its contents can be modified after creation.
String is an immutable type, meaning its contents cannot be changed once created. StringBuilder is more efficient for concatenating strings, as it avoids the overhead of creating new string objects.

 

30. What are generics? What problems do they solve?

Generics allow you to write code that works with different data types without knowing the specific type at compile-time. They help with type safety, code reuse, and remove the need for explicit casting.

 

31. What is boxing/unboxing?

Boxing is the process of converting a value type to a reference type instance.
Unboxing is the opposite, converting a reference type back to a value type.
Boxing and unboxing can incur a performance penalty as they involve additional memory allocations and type conversions.

 

32. What are Array, List, HashSet, Dictionary? Provide examples of using these data structures. What is the time complexity of operations with them (search, insertion, deletion)?

Array: A fixed-size collection of elements of the same type. Time complexity: Access O(1), Insertion/Deletion O(n).
Example: int[] numbers = { 1, 2, 3, 4, 5 };

List<T>: A dynamic array that can grow and shrink in size. Time complexity: Access O(1), Insertion/Deletion at the end O(1), Insertion/Deletion in the middle O(n).
Example: List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };

HashSet<T>: An unordered collection of unique elements. Time complexity: Add/Remove/Contains O(1) on average.Example: HashSet<string> names = new HashSet<string> { “Alice”, “Bob”, “Charlie” };

Dictionary<TKey, TValue>: A collection of key-value pairs. Time complexity: Add/Remove/Get O(1) on average. Example: Dictionary<int, string> idToName = new Dictionary<int, string> { { 1, “Alice” }, { 2, “Bob” }, { 3, “Charlie” } };

Beyond the four above, .NET ships several other collection types worth knowing: Queue<T> and Stack<T> for FIFO and LIFO access, SortedSet<T> and SortedDictionary<TKey, TValue> for ordered storage, LinkedList<T> for doubly-linked traversal, plus ConcurrentDictionary<TKey, TValue> and ConcurrentQueue<T> for thread-safe access in multi-threaded code.

 

33. What does the yield operator do?

The yield keyword returns an enumerable sequence of values from a method or iterator block, one at a time, instead of constructing the entire array or collection in memory. It allows you to work with data sequences too large to fit in memory all at once. When you iterate over a method that uses yield, the method generates the values on-the-fly, rather than creating a complete collection upfront.

 

Classes, Structures, and Interfaces

34. What is a class?

A class is a blueprint or template for creating objects. It encapsulates data (fields) and functionality (methods) into a single unit, providing a way to model real-world entities or concepts in software.

 

35. How does a class differ from an abstract class?

The key differences between a class and an abstract class are:

An abstract class cannot be instantiated directly, while a regular class can. It can have both abstract and non-abstract (implemented) methods, while a regular class can only have non-abstract methods.
A class can inherit from only one abstract class but implement multiple interfaces.

 

36. How does an abstract class differ from an interface? What are interfaces for, and what tasks do they perform?

The main differences between an abstract class and an interface are:

Abstract classes can have both abstract and non-abstract members.
Interfaces can only have abstract members (except for static and extension methods in C# 8.0 and later).
Abstract classes can have access modifiers and can provide method implementations.
Interfaces can only have public abstract members.
A class can inherit from only one abstract class but implement multiple interfaces.
Interfaces are used to achieve abstraction and define a contract.

 

37. What access modifiers do you know?

The access modifiers in C# are:

public: The type or member is accessible from anywhere.
private: The type or member is accessible only within the containing class.
protected: The type or member is accessible within the containing class or any derived classes.
internal: The type or member is accessible within the same assembly.
protected internal: The type or member is accessible within the same assembly or any derived classes.

 

38. What is the difference between regular and static classes?

A regular class can be instantiated and has both static and instance members. A static class cannot be instantiated and contains only static members. Static classes are useful for providing utility methods or constants that don’t require any instance state.

 

39. What is the difference in method overriding between the keywords new and override?

When overriding a method, the new keyword hides the base class implementation. In contrast, override replaces the base class implementation with the derived class implementation.

 

40. What is the difference between const and readonly?

const is a compile-time constant.
readonly can be set at runtime but cannot be changed after initialization.
const values are inlined by the compiler.
readonly fields are stored as instance fields.

 

41. The difference between a structure and a class. Provide examples of structures.

Structs are value types, while classes are reference types. Structs are lightweight, suitable for small, simple data structures, and are stored on the stack. Examples of structs include Point, Rectangle, and DateTime.

 

42. What are primary constructors in C#, and where are they useful?

Primary constructors, introduced for classes and structs in C# 12 (November 2023), let you declare constructor parameters directly in the type’s header. Those parameters stay in scope across the entire type body. They are available to field initializers, property initializers, plus method bodies without redeclaration.

A class with a primary constructor looks like public class Service(ILogger logger, IRepository repo) { … }. No separate constructor body. No manual field assignment. The parameters logger and repo are usable anywhere in the class. If you need them stored as fields with readonly semantics or exposed via an interface property, declare those fields explicitly and assign them in their initializers.

Primary constructors shorten dependency-injected service classes, DTOs, plus small wrapper types. They pair naturally with records, which have always used primary constructor syntax. The trade-offs are real: only one primary constructor per type, and primary constructor parameters are not properties by default on a class (they are on a record). For complex initialization with validation or branching, a traditional constructor still reads more clearly.

 

Asynchronicity

43. What is asynchronicity, and how does it differ from multithreading?

Asynchronicity allows a program to perform other tasks while waiting for a long-running operation to complete without blocking the main thread. It is different from multithreading, which involves running multiple threads concurrently. With asynchronicity, the application can continue executing other code while the asynchronous operation is in progress, improving overall responsiveness and efficiency. On the other hand, multithreading involves parallel execution of multiple threads, which can be useful for CPU-bound tasks but requires more complex synchronization and resource management.

 

44. What keywords are used to work with asynchronicity in code?

The keywords used for asynchronicity in C# are async and await.

 

45. What do the keywords async/await mean?

The async keyword marks a method as asynchronous, allowing it to use the await keyword to pause the execution of the method until the awaited asynchronous operation completes. It enables the method to return control to the caller while the asynchronous operation is in progress, improving the application’s overall responsiveness.

 

Databases

46. The difference between relational and non-relational databases, the pros and cons of using both options.

Relational databases (SQL) store data in tables with defined schemas, using a structured query language (SQL) for data manipulation and retrieval. They excel at handling structured data and complex queries. Relational databases are generally stronger regarding data integrity, consistency, and complex querying.

Non-relational (NoSQL) databases use flexible, schema-less data models, such as key-value, document-oriented, or graph-based. They are better suited for handling unstructured data and high scalability requirements. Non-relational databases offer higher availability, partition tolerance, and scalability.

 

47. What are indexes in RDBMS?

Indexes in RDBMS are additional data structures that improve the speed of data retrieval operations, such as SELECT queries. Indexes create a sorted list of values from a table column and pointers to the corresponding rows.

 

48. What types of JOINs exist in SQL?

The main types of SQL JOINs are:

INNER JOIN: Returns rows that have matching values in both tables.
LEFT JOIN (LEFT OUTER JOIN): Returns all rows from the left table and the matching rows from the right table.
RIGHT JOIN (RIGHT OUTER JOIN): Returns all rows from the right table and the matching rows from the left table.
FULL JOIN (FULL OUTER JOIN): Returns all rows from both tables, whether or not there is a match.

 

Testing

49. What is the fundamental difference between unit tests and integration tests?

The fundamental difference between unit tests and integration tests is the scope and focus of the tests:

Unit tests focus on testing individual units or components of a system in isolation, verifying that each unit works as expected. They target the smallest testable parts of an application, such as individual methods or classes, and aim to ensure the correctness of the implementation.

Integration tests, on the other hand, verify that different components of a system work together correctly. They test the interactions between multiple units or modules, ensuring the overall system functions as expected. Integration tests are typically performed after unit tests, and they help identify issues that may arise from integrating different parts of the application.

The main difference is that unit tests target individual units of code, while integration tests focus on the interactions and data flow between those units. Unit tests are typically easier to write, maintain, and run, while integration tests provide a more comprehensive understanding of the system’s behavior.

 

50. What are unit tests used for?

Unit tests are used to verify the correctness of individual units of code (methods, classes, or components) in isolation. By testing units in isolation, you ensure each building block functions correctly, leading to a reliable application.

Unit tests verify the correctness of individual units of code (methods, classes, or components) in isolation. By testing each unit on its own, you ensure that every building block functions correctly, which leads to a reliable application.

The practical benefit is catching bugs early and locking in behavior so future changes do not silently break working code. Unit tests also produce a safety net when the codebase needs refactoring. The trade-off is the development effort and the ongoing maintenance cost. Tests need updating as the code evolves.

 

51. From what three logical blocks is a unit test composed?

A unit test consists of three logical blocks:
Arrange: Set up the necessary test data and preconditions.
Act: Execute the code being tested.
Assert: Verify that the observed outcome matches the expected outcome.

.NET Interview Questions for Middle Developers

Middle .NET interviews target candidates with roughly 3–6 years of experience. The conversation pushes past memorized definitions into how concepts hold up under realistic constraints. Expect questions on LINQ deferred execution, garbage collector internals, dependency injection lifetimes, and the difference between Task and Thread. Architecture and database modeling typically enter the conversation by the second round.

Mid-level .NET developer

General .NET Interview Questions

52. Describe in as much detail as possible what happens at the HTTP level when you type google.com in a browser.

When you type “google.com” in a browser, the following happens at the HTTP level:

The browser first resolves the domain name “google.com” to an IP address using the Domain Name System (DNS). The browser sends a DNS query to a DNS server, which looks up the IP address associated with the domain.

Once the IP address is obtained, the browser initiates a TCP connection with the web server at that IP address, using the HTTP protocol on port 80 (the default HTTP port).

The browser then sends an HTTP GET request to the web server, requesting the root resource (usually the home page). The request includes headers with information about the client, such as the browser type, accepted file types, and other metadata.

The web server receives the request, processes it, and generates a response. The response includes an HTTP status code (e.g., 200 for successful, 404 for not found), response headers with metadata about the response, and the web page’s actual content (usually in HTML format).

The browser receives the response, parses the HTML, and renders the web page. As the page loads, the browser may send additional requests for resources referenced in the HTML, such as images, stylesheets, and JavaScript files.

The browser continues to fetch all the necessary resources and assembles the complete web page, displaying it to the user.

HTTPS (Hypertext Transfer Protocol Secure) is a secure version of the HTTP protocol that adds encryption to the communication between the client (browser) and the web server.

 

53. How does HTTPS work?

HTTPS works as follows:

01
The client (browser) initiates a connection to the web server using the HTTPS protocol, typically on port 443.
02
The web server presents its SSL/TLS certificate, which contains its public key and other information about the server's identity.
03
The client verifies the server's certificate, checking that it was issued by a trusted Certificate Authority (CA) and that the domain name matches the expected website.
04
The client and server establish a secure, encrypted connection if the certificate is valid.
05
All subsequent communication between the client and server is encrypted.

HTTPS helps protect against man-in-the-middle attacks, eavesdropping, and other security threats.

 

54. What is your understanding of SOLID principles?

The SOLID principles are a set of guidelines for writing clean, maintainable, and extensible object-oriented code:

  • Single Responsibility Principle (SRP): A class should have only one reason to change.
  • Open/Closed Principle (OCP): Software entities (classes, modules, functions, etc.) should be open for extension but closed for modification.
  • Liskov Substitution Principle (LSP): Subtypes must be substitutable for their base types.
  • Clients should not be forced to depend on interfaces they do not use.
  • Dependency Inversion Principle (DIP): High-level modules should not depend on low-level modules. Both should depend on abstractions.

Adhering to the SOLID principles helps create modular, flexible, and maintainable code that is easier to understand, test, and extend over time.

 

55. What serialization protocols do you know, and where are they used?

Some common serialization protocols used in .NET include:

  • JSON (JavaScript Object Notation):A lightweight, text-based format used for data exchange. Commonly used for web services and APIs.
  • XML (Extensible Markup Language): A more verbose, structured format widely used for data exchange and configuration files.
  • Binary serialization: A compact, binary format for serializing .NET objects. Useful for transmitting data over the network or persisting objects to storage.
  • Protocol Buffers (protobuf): A binary serialization format developed by Google, optimized for performance and size.

The choice of serialization protocol depends on factors such as the data’s size and complexity and the system’s compatibility needs.

 

56. What is a pure function, and what are its advantages?

A pure function is a function that:

  • Always returns the same output for a given input (no side effects).
  • Does not modify any state outside of its local scope.

The advantages of using pure functions include:

  • Predictability: Pure functions always produce the same output for the same input, making the code more predictable and easier to reason about.
  • Testability: Pure functions can be easily tested in isolation, as they don't depend on external state.
  • Parallelism: Pure functions can be safely executed in parallel, as they don't interfere with each other.
  • Referential transparency: Expressions using pure functions can be replaced by their result without affecting the program's behavior.

Pure functions promote modularity, testability, and functional programming principles, leading to more maintainable and robust code.

 

57. What is dependency injection, and why is it useful?

Dependency Injection (DI) is a design pattern that allows you to decouple the creation and management of object dependencies from the objects that depend on them. Instead of directly creating dependencies, objects receive their dependencies from an external source. For example, through the constructor, method parameters, or properties.

DI is useful because it:

  • Promotes loose coupling between components, making the code more modular and testable.
  • Allows for easy substitution of implementations, enabling flexibility and adaptability.
  • Facilitates the use of abstractions, which can improve the system's overall design.
  • Simplifies the management of object lifetime and resource allocation.

By using DI, you can create more maintainable, extensible, and testable applications, as the dependencies are managed externally.

 

58. What are cohesion and coupling, and what do they mean?

Cohesion and coupling are two fundamental software design principles:

Cohesion refers to the degree to which the elements inside a module (e.g., a class or a function) belong together. High cohesion means that the elements within a module are strongly related and work together to achieve a specific purpose. Low cohesion indicates that the elements within a module are loosely related or unrelated, making the module harder to understand and maintain.

Coupling refers to the degree of interdependence between modules. Low coupling means that modules have minimal dependencies on each other, making the system more flexible and easier to modify. High coupling indicates that modules have strong dependencies, which can make the system more rigid and harder to change.

 

59. What are IaaS, PaaS, and SaaS, and what are the differences between them?

IaaS, PaaS, and SaaS are different service models in cloud computing:

IaaS (Infrastructure as a Service): Provides access to virtualized computing resources, such as virtual machines, storage, and networking. The cloud provider manages the underlying infrastructure, while the user controls the operating system, applications, and data.

PaaS (Platform as a Service): Provides a platform for developing, testing, and deploying applications, including the operating system, middleware, and runtime environment. The cloud provider manages the underlying infrastructure and platform while the user focuses on deploying and managing their applications.

SaaS (Software as a Service): Provides access to software applications hosted and managed by the cloud provider. Users access the software through a web browser or API; the cloud provider is responsible for the infrastructure, platform, and application management.

The main differences lie in the level of control and responsibility the user has over the various components of the system. IaaS offers the most control, PaaS offers a balance of control and abstraction, and SaaS offers the least control but the highest level of abstraction.

 

60. What debugging techniques do you use?

Some common debugging techniques include:

  • Setting breakpoints in the code to pause execution and inspect variables.
  • Stepping through the code line by line to understand the flow of execution.
  • Using the debugger's "Watch" and "Immediate" windows to evaluate expressions and monitor variable values.
  • Leveraging logging and tracing to output relevant information during program execution.
  • Analyzing stack traces to identify the root cause of exceptions or unexpected behavior.
  • Profiling the application to identify performance bottlenecks and optimize the code.
  • Leveraging debugging tools, such as PerfView, dotTrace, or Visual Studio's built-in profiler to gain deeper insights into the application's runtime behavior.

The choice of debugging technique depends on the nature of the problem, the complexity of the application, and the available tooling.

 

61. What design patterns do you know? Explain the essence of the ones you mentioned.

Some design patterns include:

  • Singleton ensures a class has only one instance and provides a global point of access to it. Useful for managing global state or resources.
  • Factory defines an interface for creating objects but lets subclasses decide which class to instantiate. Helpful for creating objects without exposing the creation logic.
  • Adapter converts the interface of a class into another interface the client expects. Allows classes with incompatible interfaces to work together.
  • Observer defines a one-to-many dependency between objects. So that when one object changes state, all its dependents are notified and updated automatically. Useful for implementing event-driven architectures.
  • Strategy defines a family of algorithms, encapsulates each one, and makes them interchangeable. Allows the algorithm used by a class to be selected at runtime.

These patterns help promote modularity, flexibility, and reusability in software design, making the code more maintainable over time.

 

62. What is the essence of the Singleton pattern? Why is it also called an anti-pattern?

The Singleton pattern ensures that a class has only one instance and provides a global point of access to it. The essence of the Singleton pattern is to have a private constructor and a static method that returns the single instance of the class.

The Singleton pattern is sometimes considered an anti-pattern because it can introduce a global state, making the code harder to test.

Alternatives to the Singleton pattern include using Dependency Injection to manage the lifetime of objects or using static classes (in C#) to provide global access to functionality without needing a Singleton instance.

 

63. What is the purpose of the Strategy pattern?

The purpose of the Strategy pattern is to define a family of algorithms, encapsulate each one, and make them interchangeable. This way, the algorithm can be used by a class to be selected at runtime rather than being hard-coded.

The key benefits of the Strategy pattern are:

  • Flexibility: By encapsulating different algorithms in separate classes, the Strategy pattern makes it easy to add new algorithms or modify existing ones without changing the context in which they are used.
  • Reduced conditional logic: Instead of using conditional statements to determine which algorithm to use, the Strategy pattern delegates the choice of algorithm to the client, making the code more readable and maintainable.
  • Testability: The algorithms can be tested in isolation, as they are decoupled from the context in which they are used.

The Strategy pattern is useful in scenarios where you need to support multiple algorithms or behaviors.

 

64. What are the key differences between distributed systems and monolithic ones?

The key differences between distributed systems and monolithic ones are:

  • Architecture: Distributed systems are composed of multiple, independently deployable components that communicate with each other. Monolithic systems are a single, tightly coupled application.
  • Scalability:Distributed systems can scale individual components horizontally, adding more instances as needed. Monolithic systems can be more challenging to scale, as the entire application needs to be scaled.
  • Complexity: Distributed systems are generally more complex. They need to handle issues like network failures, eventual consistency, and coordinating the interactions between components.
  • Development and Deployment: Distributed systems allow for independent development and deployment of components. Monolithic systems require the entire application to be deployed together.
  • Reliability: Distributed systems can be more resilient, as the failure of one component does not necessarily bring down the entire system. Monolithic systems have a single point of failure.

 

65. What design patterns for distributed systems do you know?

Some design patterns used in distributed systems include:

  • Microservices: Organizes an application as a collection of loosely coupled, independently deployable services.
  • API Gateway: Serves as a single entry point for clients to access the underlying microservices.
  • Circuit Breaker: Prevents cascading failures in distributed systems by stopping calls to a failing service.
  • Event-Driven Architecture: Uses an event bus or message broker to decouple the components of a distributed system.
  • CQRS (Command Query Responsibility Segregation): Separates the read and write operations responsibilities, often used in event-driven architectures.

 

66. What are the principles of a Message Bus? Why can duplicates occur in queues?

The principles of a Message Bus are:

  • Loose Coupling: The components of the system are decoupled, communicating asynchronously through the message bus.
  • Scalability: The message bus can handle increasing message loads by adding more message brokers or consumers.
  • Reliability: To ensure reliable delivery, the message bus provides features like message persistence, retries, and dead-letter queues.

Duplicates can occur in queues for various reasons, such as network failures, process restarts, or message redelivery. To handle this, consumers should be designed to be idempotent, meaning they can safely process the same message multiple times.

 

67. What principles of building idempotent services do you know?

Idempotent services produce the same observable result whether they process a given request once or many times. The principles for building them:

  • Assign a unique request identifier (idempotency key) per logical operation. Store processed keys with their outcome so retries return the cached result.
  • Design state transitions so re-applying the same change is a no-op. For example, UPDATE orders SET status = 'paid' WHERE id = X AND status <> 'paid' is safe to run twice.
  • Gate side effects on the idempotency key. Outbound email or card charges or downstream API calls must each pass through the same key check, otherwise duplicate deliveries produce duplicate actions.
  • Persist the idempotency record in the same transaction as the business state change. Partial commits break the invariant.
  • Set retention on idempotency records to match the upstream retry window, typically 24 to 72 hours.

Idempotency matters because at-least-once delivery from message brokers, retry policies in HTTP clients, plus network partitions all produce duplicate requests at scale.

 

68. Explain how asynchronous methods work. How does asynchronicity differ from parallelism?

Asynchronous methods in .NET let a calling thread initiate an operation and continue executing other work without waiting for the operation to complete. The mechanism rests on async and await plus the Task-based Asynchronous Pattern (TAP). When you call an async method, it returns a Task or Task<T> representing the pending operation. Code that awaits the task suspends the current method and releases the thread back to the thread pool. The method resumes on a continuation when the awaited operation completes.

Asynchronicity differs from parallelism in intent and mechanism. Asynchronicity lets a single thread stay productive by switching between tasks during I/O waits. It shines on I/O-bound workloads such as database queries, HTTP calls, plus file operations. Parallelism executes multiple tasks concurrently on multiple threads. It shines on CPU-bound workloads that split into independent subtasks. Async unblocks; parallel divides.

Many real systems use both. Async releases threads during I/O so the thread pool has capacity for CPU-bound parallel work running on other threads.

 

.NET Framework and Runtime Interview Questions

69. What exceptions can’t be caught in a catch block?

In C#, certain exceptions cannot be caught in a catch block. These exceptions are known as unhandled exceptions, and they typically occur due to critical errors or resource constraints. Some examples of exceptions that cannot be caught include:

  • StackOverflowException: This exception occurs when the program runs out of available memory on the stack.
  • OutOfMemoryException: This exception occurs when the program runs out of available memory on the managed heap.
  • ThreadAbortException: This exception occurs when a thread is aborted due to a call to the Thread.Abort method.
  • ExecutionEngineException: This exception occurs when there is an internal error in the common language runtime (CLR).

These exceptions are considered as unhandled exceptions, and they usually result in the termination of the application or the AppDomain.

 

70. Explain the difference between deferred and immediate execution in LINQ.

In LINQ (Language Integrated Query), there are two types of execution modes: deferred execution and immediate execution. The difference lies in when the query is actually evaluated and executed.

Deferred Execution:
In deferred execution mode, the LINQ query is not executed until the result is actually enumerated or accessed. The query is constructed and stored as an expression tree, and the actual evaluation is deferred until the last possible moment. Deferred execution is the default behavior for most LINQ queries.

Immediate Execution:
In immediate execution mode, the LINQ query is executed immediately, and the results are stored in a data structure (e.g., a list or array). This mode is typically used when you need to work with the query results multiple times or when you need to perform operations that cannot be expressed as a query expression.

 

71. How do you configure dependency injection and middleware in ASP.NET Core?

ASP.NET Core configures services and middleware in Program.cs using the minimal hosting model, which has been the default since .NET 6 (November 2021). The pattern is:

var builder = WebApplication.CreateBuilder(args);

// Register services with the DI container
builder.Services.AddControllers();
builder.Services.AddDbContext<AppDbContext>(opt =>
opt.UseSqlServer(builder.Configuration.GetConnectionString(“Default”)));
builder.Services.AddScoped<IOrderService, OrderService>();

var app = builder.Build();

// Configure the HTTP request pipeline (middleware)
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();

app.Run();

builder.Services registers services with the dependency injection container. Typical registrations include the DbContext, MVC or minimal API services, authentication handlers, options bindings, and any third-party library that integrates with DI. The app.Use… calls register middleware in the order they execute.

Older ASP.NET Core templates (pre-.NET 6) split this work between Startup.cs’s ConfigureServices method (for DI) and Configure method (for the pipeline). The Startup.cs pattern still works for migration scenarios, but new projects use the Program.cs minimal hosting model.

 

72. What is the difference between services.AddTransient and services.AddScoped in ASP.NET Core?

In ASP.NET Core, services.AddTransient and services.AddScoped are methods used to register services with the built-in Dependency Injection (DI) container. The main difference between them lies in the lifetime and scope of the registered service instances.

services.AddTransient:
When a service is registered as transient using services.AddTransient, a new service instance is created every time it is requested from the DI container. It means that a new instance of that service will be created each time a transient service is injected into another class or component.
Transient services are suitable for stateless services or services that do not maintain any state across multiple requests.

services.AddScoped:
When a service is registered as scoped using services.AddScoped, a single instance of the service is created and shared within the same scope. In ASP.NET Core, the scope is typically tied to the current HTTP request. This means that within the same HTTP request, the same instance of the scoped service will be used for all instances that require that service.However, for a new HTTP request, a new instance of the scoped service will be created and used for that request’s scope.

Scoped services are suitable for services that maintain a state related to the current request or operation, such as services that interact with the HTTP context or databases.

The main difference between transient and scoped services lies in the lifetime and sharing of instances:

Transient: A new instance is created every time the service is requested.
Scoped: A single instance is created and shared within the same scope (e.g., HTTP request).

In general, you should use transient services for stateless services or services that do not maintain any state across multiple requests. Scoped services should be used for services that need to maintain state related to the current request or operation.

 

73. What is Kestrel?

Kestrel is a cross-platform web server for ASP.NET Core applications. It is an open-source web server that was developed by Microsoft as part of the .NET Core project. Kestrel is designed to be lightweight, high-performance, and cross-platform, making it suitable for various deployment scenarios.

Here are some key features and characteristics of Kestrel:

  • Cross-Platform: Kestrel is a cross-platform web server that can run on multiple operating systems, including Windows, Linux, and macOS.
  • Lightweight and High-Performance: Kestrel is designed to be lightweight and highly performant. It uses asynchronous I/O operations and a lean architecture, efficiently handling many concurrent connections. Integration with ASP.NET Core: Kestrel is tightly integrated with ASP.NET Core and is the default web server hosting ASP.NET Core applications.
  • Modular Design: Kestrel has a modular design, allowing developers to configure and extend its functionality. For example, developers can add support for additional protocols or implement custom middleware components.
  • Reverse Proxy Support: While Kestrel is a capable web server, exposing it directly to the internet is not recommended. Instead, it is typically used in conjunction with a reverse proxy server. Such as Internet Information Services (IIS), Nginx, or Apache, which handles tasks like SSL termination, load balancing, and static file serving. Containerization and Cloud Deployments: Kestrel's lightweight and cross-platform nature makes it well-suited for containerized deployments and cloud environments.

Kestrel is designed to be a lean and efficient web server for ASP.NET Core applications, providing high performance and cross-platform support. However, it is typically used in conjunction with a reverse proxy server in production environments to ensure secure and scalable deployments.

 

74. Describe the ASP.NET Core MVC request pipeline.

The ASP.NET Core MVC request pipeline handles an incoming HTTP request from the moment Kestrel accepts it through to the response sent back to the client. The main stages:

  • Routing: The first step in the pipeline is to route the incoming request to the appropriate controller and action method based on the URL and routing rules defined in the application.
  • Model Binding: The model binding process occurs if the action method expects input parameters. During model binding, the framework attempts to map the incoming request data (query string, form data, etc.) to the action method's parameters.
  • Action Filters: Any action filters configured for the controller or action are executed before executing the action method. Action filters allow developers to add custom logic that runs before or after the action method execution.
  • Action Method Execution: The appropriate action method on the controller is executed, and any logic within the method is performed.
  • Action Result Creation: After the action method execution, an action result is created. The action result represents the outcome of the action method and contains the data or instructions for generating the response.
  • Result Filters: Any result filters configured for the controller or action are executed. Result filters allow developers to modify or add logic to the action result before it is rendered.
  • View Engine Processing: If the action result is a view result, the view engine processes the corresponding view template and generates the final HTML output.
  • Response: The final response, which may include the HTML output from the view engine or other data (such as JSON or XML), is sent back to the client.

 

75. How do you configure response caching in ASP.NET Core?

ASP.NET Core offers two complementary approaches to caching HTTP responses: client-side caching headers and server-side output caching.

Client-side caching uses the Cache-Control and Expires response headers. Apply them via the [ResponseCache] attribute on a controller action or via the Response Caching middleware (app.UseResponseCaching()). These instruct browsers and intermediate proxies to cache the response for a specified duration. They reduce load by preventing the request from reaching your server in the first place, but they cannot serve cached responses on the server itself.

Server-side caching uses the Output Caching middleware, added in .NET 7 (app.UseOutputCache()). Output Caching stores rendered responses in memory or in a distributed cache such as Redis, then serves them directly on subsequent matching requests without invoking the controller action. You apply it per endpoint with [OutputCache(Duration = 60)] or via a named policy.

For caching application data instead of full responses, use IMemoryCache for in-process state plus IDistributedCache for a shared L2 backing store, or HybridCache for the unified two-tier API introduced in .NET 9.

 

Memory Management

76. What are the heap and the stack? Differences, principles of operation.

The heap and the stack are two different memory regions in the computer’s memory that are used to store data during the execution of a program.

The Stack

  • The stack is a memory region used for static memory allocation.
  • It is organized as a last-in, first-out (LIFO) data structure, where the last item pushed onto the stack is the first one to be popped off.
  • The stack stores function call information, such as local variables, parameters, and return addresses.
  • Memory allocation and deallocation on the stack are very fast operations.
  • The stack size is limited and determined at compile-time or during thread creation.
  • When a function is called, memory is allocated on the stack for its local variables and parameters.
  • When the function returns, the allocated memory is automatically deallocated (popped off the stack).

The Heap

  • The heap is a memory region used for dynamic memory allocation.
  • It is organized as a free pool of memory blocks that can be allocated and deallocated at runtime.
  • Memory allocation and deallocation on the heap are relatively slower operations than the stack.
  • The heap size is not fixed and can grow or shrink as needed during program execution.
  • Objects and data structures with a longer lifetime or dynamically created during runtime are stored on the heap.
  • Memory allocation on the heap explicitly uses operators like new in C#. At the same time, deallocation is usually handled automatically by the garbage collector in managed languages like C#.

The stack is used for static memory allocation and automatic memory management. In contrast, the heap is used for dynamic memory allocation and requires manual or automatic memory management (e.g., garbage collection). The stack is faster and has a limited size, while the heap is slower but can grow dynamically.

 

77. How does the Garbage Collector work?

The Garbage Collector (GC) is a key component of the .NET runtime. GC automatically manages the allocation and deallocation of memory for managed objects on the heap. Garbage Collector works by periodically scanning the managed heap and identifying objects that are no longer reachable, and reclaiming the memory occupied by those objects.

Here’s a general overview of how the Garbage Collector works:

  • Marking Phase: During this phase, the GC identifies the root objects (objects that are currently in use, such as static objects, objects on the stack, and objects referenced by CPU registers). It then traverses all references from these root objects, marking all reachable objects as "live."
  • Marking Phase Ending: After marking all live objects, the GC checks for sufficient memory to continue execution. If not, it proceeds to the next phase.
  • Relocating Phase: In this phase, the GC compacts the heap by moving all live objects to one end of the heap, creating a contiguous block of free memory.
  • Reclaiming Phase: After compacting the heap, the GC reclaims the memory occupied by unreachable (dead) objects, making it available for future allocations.

The GC employs various techniques and algorithms to optimize its performance. These techniques include generational garbage collection, which divides the heap into generations based on object lifetime, and background garbage collection, which allows the GC to run concurrently with the application’s threads.

 

78. Why do we need the using keyword in C# if .NET has automatic memory management? How is this related to the Disposable pattern, and why is such a complex pattern needed for managed and unmanaged resources?

The using keyword in C# is needed to ensure proper disposal of unmanaged resources, even with .NET’s automatic memory management for managed resources. It’s related to the IDisposable interface and the Disposable pattern, which provides a way to encapsulate the acquisition and release of unmanaged resources. This complex pattern is necessary because while the .NET Garbage Collector handles managed objects, it doesn’t manage unmanaged resources, which must be explicitly released to prevent leaks.

 

79. What are the peculiarities of working with the Large Object Heap?

Working with the Large Object Heap (LOH) in .NET has several peculiarities:

  • Objects larger than a certain size threshold (typically 85KB on 64-bit systems) are allocated on the LOH instead of the regular managed heap.
  • The LOH is more prone to fragmentation, as large objects are less likely to be collected and compacted regularly.
  • Objects on the LOH are not divided into generations and are not compacted as aggressively as regular objects.
  • Collecting and compacting objects on the LOH can be expensive, leading to longer garbage collection pauses.
  • Large objects on the LOH can consume significant memory, potentially causing memory pressure.
  • Finalizing large objects on the LOH is more expensive due to their size and the overhead of moving them.

Data Types, Collections, and Data Structures

80. When is a generic class of a specific type generated – at runtime or compile-time?

A generic class of a specific type is generated at compile-time through a process called code generation or specialization. When you use a generic class with a specific type argument, the compiler generates the IL (Intermediate Language) code for that specialized version of the class.

 

81. What is reflection?

Reflection is a mechanism in .NET that allows code to inspect and interact with itself at runtime. This mechanism provides a way to dynamically discover and manipulate types, fields, methods, properties, and other metadata of loaded assemblies during program execution.

 

82. Tell me about the `LinkedList<T>` collection. How does it differ from other collections?

The LinkedList<T> is a doubly-linked list collection in .NET. It differs from other collections like List<T> and arrays in that it maintains a logical order of its elements and allows efficient insertion and removal operations at any point in the list. Unlike arrays, LinkedList<T> has no need to shift elements when adding or removing items, making it more efficient for frequent modifications.

 

83. What is an indexer?

An indexer is a special property in C# that allows instances of a class or struct to be accessed similarly to arrays or collections using an index or a set of indices. Indexers provide a convenient syntax for accessing and manipulating data within an object, making the object behave like a virtual array or dictionary.

 

84. What is an immutable object? What are the benefits of using immutable objects? Propose a way to implement it in .NET.

An immutable object is an object whose state cannot be modified after creation. Once an immutable object is instantiated, its properties and fields remain constant throughout its lifetime.

Benefits of using immutable objects include:

Thread safety: Immutable objects are inherently thread-safe, as their state cannot be modified concurrently.
Simplicity: Immutable objects are simpler to reason about and debug, as their behavior is predictable and deterministic.
Caching: Immutable objects can be safely cached, as their state never changes.

To implement an immutable object in .NET, you can follow these steps:

  • Make the class immutable by removing all public setters and making all instance fields read-only or private.
  • Initialize all instance fields through the constructor or Factory methods.
  • Avoid exposing public methods that modify the object's state.
  • Return new instances instead of modifying existing ones when state changes are required.
  • Consider using read-only collections or immutable collection types for any collections the class exposes.

Following these principles, you can create immutable objects that provide thread safety, simplicity, and caching benefits in your .NET applications.

 

85. When should you use StringBuilder, and when should you use string? How does StringBuilder work?

You should use StringBuilder when performing multiple string operations, such as concatenations, insertions, or modifications.

string is immutable, meaning that any operation that modifies a string creates a new string object, which can lead to performance issues and increased memory usage.

StringBuilder is a mutable object that provides a more efficient way to build strings dynamically. It works by pre-allocating a buffer in memory and allowing you to modify the contents of that buffer directly without creating new string objects for each operation. This approach is more efficient, especially when dealing with large strings or performing many string operations.

Here’s a simplified overview of how StringBuilder works:

01
StringBuilder allocates an initial buffer in memory to store characters
02
As you append, insert, or modify characters, StringBuilder updates the buffer directly without creating new string objects
03
If the buffer becomes too small to hold the new characters, StringBuilder automatically resizes the buffer to accommodate the additional characters
04
When you need the final string, you can call the ToString() method, which creates a new string instance from the contents of the buffer

In general, you should use StringBuilder when performing multiple string operations, especially in loops or performance-critical code. For simple string operations or when you don’t need to modify the string, it’s fine to use the string type.

 

86. What is tree balancing?

Tree balancing is a technique used in self-balancing binary search trees (such as AVL trees or Red-Black trees) to ensure that the tree remains balanced and maintains its efficiency for operations like insertion, deletion, and search. A balanced tree is one where the heights of the left and right subtrees of every node differ by at most one.

Tree balancing involves performing rotations (left or right) on nodes in the tree to maintain the balance after insertions or deletions. These rotations help redistribute the nodes in the tree, ensuring that the height of the tree remains logarithmic with respect to the number of nodes, which is crucial for efficient operations.

Balancing a tree helps maintain the time complexity of operations like search, insertion, and deletion at O(log n), where n is the number of nodes in the tree. Without balancing, a binary search tree can degenerate into a linked list in the worst case, leading to linear time complexity for these operations.

 

87. What are key-value structures?

Key-value structures, also known as associative arrays or dictionaries, are data structures that store and organize data as key-value pairs. Each element is associated with a unique key used to access and retrieve the corresponding value in a key-value structure.

Key-value structures are widely used in various applications, such as caching systems, databases, and data processing pipelines. They provide an efficient way to store and retrieve data based on a key, which can be a primitive type (e.g., integer, string) or a custom object.

Examples of key-value structures in .NET include:

Dictionary<TKey, TValue>: A generic collection that stores key-value pairs, where the keys are unique.
Hashtable: A non-generic collection that stores key-value pairs, similar to Dictionary<TKey, TValue>.
SortedDictionary<TKey, TValue>: A sorted collection that stores key-value pairs in ascending order based on the keys.
SortedList<TKey, TValue>: A sorted collection that stores key-value pairs in a list-like structure.

Key-value structures provide efficient lookup, insertion, and deletion operations, with an average time complexity of O(1) for most operations when implemented correctly (e.g., using hash tables).

 

88. What is a hash function, and why are hash tables needed?

A hash function is a mathematical function that takes an input (e.g., a string, an object, or data collection) and produces a fixed-size output, typically an integer value, known as a hash code or hash value. Hash functions are designed to distribute their outputs in a uniform and pseudo-random manner across the entire range of possible hash values.

Hash tables are data structures that use hash functions to store and retrieve data efficiently. Hash tables are needed because they provide fast average-case time complexity for common operations like insertion, deletion, and lookup, which are typically O(1) on average.

Hash tables are widely used in various applications, such as caching systems, databases, compilers, and data processing pipelines, due to their efficiency in storing and retrieving data based on keys.

 

89. What properties should an ideal hash function have?

An ideal hash function should have the following properties:

  • Determinism: The hash function should always produce the same output for a given input. This property ensures consistency and predictability in the behavior of the hash function.
  • Uniform distribution: The hash function should distribute its outputs as uniformly as possible across the entire range of possible hash values. This property helps minimize collisions in hash tables and ensures efficient use of storage space.
  • Avalanche effect: A small change in the input should result in a significant change in the output hash value. This property helps prevent predictable patterns in the hash values and makes it harder to cause collisions intentionally.
  • Speed: The hash function should be computationally efficient and fast to calculate, as it may be called frequently in performance-critical applications.
  • Collision resistance: Finding two different inputs that produce the same hash value (collisions) should be computationally infeasible. This property is crucial for applications that rely on the uniqueness of hash values, such as cryptographic hash functions.
  • Irreversibility: It should be computationally infeasible to reconstruct the original input from the hash value alone. This property is essential for applications that use hash functions for data integrity or security purposes.

 

90. What are collisions, and how do you deal with them?

Collisions in hash tables occur when different keys are mapped to the same index by the hash function. Common techniques to handle collisions include separate chaining, open addressing, and rehashing.

 

91. What is the time complexity of CRUD operations on `Dictionary<K,V>` in .NET?

The time complexity of CRUD operations on Dictionary<K,V> in .NET is O(1) on average for retrieval, insertion, and removal, assuming a good hash function and proper load factor management.

 

92. Where are arrays stored? Primitive type arrays?

Arrays are stored on the managed heap in .NET. Primitive type arrays are stored as a contiguous block of memory on the managed heap.

 

93. What is the difference between an array (`T []`) and a list (`List<T>`)?

An array (T[]) has a fixed size that cannot be changed after creation, while a List<T> is a resizable collection that can grow or shrink dynamically.

 

94. What is the difference between IList<T> and IEnumerable<T>?

IList<T> is a collection that provides indexed access and modification methods, while IEnumerable<T> is a more basic interface for iterating over a collection.

 

95. Why do we need Enumerable, Observable, AsyncEnumerable, and what data retrieval models do they implement?

Enumerable, Observable, and AsyncEnumerable implement different data retrieval models:
Enumerable for synchronous pull-based retrieval.
Observable for push-based asynchronous retrieval.
AsyncEnumerable for asynchronous pull-based retrieval.

 

96. What is the difference between IEnumerable and IQueryable?

IEnumerable represents an in-memory collection, while IQueryable represents a query that can be executed against a data source (e.g., a database).

 

97. What are enum flags?

Enum flags are special values that can be combined using bitwise operations to represent multiple states or options simultaneously.

 

Databases

98. Explain normal forms in RDBMS.

Normal forms are rules or guidelines for designing relational database tables to minimize data redundancy and improve data integrity. The main normal forms are:

 

01
First Normal Form (1NF):
Eliminates multi-valued attributes and ensures that each cell in a table contains a single value.
02
Second Normal Form (2NF):
Meets 1NF and ensures that non-key attributes fully depend on the primary key.
03
Third Normal Form (3NF):
Meets 2NF and eliminates transitive dependencies, where non-key attributes depend on other non-key attributes.
04
Boyce-Codd Normal Form (BCNF):
Meets 3NF and ensures that every determinant is a candidate key.
05
Fourth Normal Form (4NF):
Meets BCNF and eliminates multi-valued dependencies.
06
Fifth Normal Form (5NF):
Meets 4NF and ensures that there are no redundant joins, also known as join dependencies.

Higher normal forms aim to eliminate more data redundancy and dependencies, leading to a more normalized database design.

Denormalization is the opposite move. Teams selectively reintroduce redundancy (duplicated columns, computed totals stored alongside their inputs) to improve read performance, accepting the consistency and update-complexity cost that normalization originally aimed to avoid.

 

99. What is an index in a database?

An index in a database is a data structure that stores a subset of data from a table to improve the speed of data retrieval operations. It works similarly to an index in a book, pointing to the location of specific data values within the table. Indexes are typically created on one or more columns of a table.

 

100. When should you use indexes? Pros and cons.

Indexes should be used when:

– Frequent queries involve searching, sorting, or retrieving data based on one or more columns.

– You need to enforce uniqueness constraints or foreign key relationships.

– You want to improve the performance of join operations between tables.

Pros of using indexes
Cons of using indexes

Faster data retrieval for queries involving indexed columns

Additional storage space is required for the index data structures

Improved query performance, especially for large tables

Due to index maintenance, increased overhead for data modification operations (inserts, updates, deletes)

Enforced uniqueness and integrity constraints

Potential for index fragmentation over time, leading to performance degradation

101. What types of indexes exist? How do they differ?

There are several types of indexes in databases:

  • Clustered Index: Physically reorders the data rows in the table based on the index key values. Only one clustered index is allowed per table.
  • Non-Clustered Index: Stores the index keys and pointers to the corresponding data rows, keeping the data rows' physical order unchanged. Multiple non-clustered indexes are allowed per table.
  • Unique Index: Ensures that the indexed column(s) have unique values across all rows in the table.
  • Composite Index: Indexes multiple columns within the same index structure.
  • Covering Index: Includes all the columns required for a query, eliminating the need to access the data rows directly.
  • Full-Text Index: Optimized for text-based searches, allowing for pattern matching and linguistic analysis.
  • Spatial Index: Used for efficiently querying and retrieving spatial data, such as geographic coordinates.

These index types differ in structure, storage mechanisms, and optimizations for various queries and data access patterns.

 

102. What is ACID?

ACID is an acronym that represents four essential properties of database transactions:

Atomicity: A transaction is an indivisible unit of work; either all of its operations are completed successfully or none are executed.
Consistency: A transaction must leave the database in a valid state, following all defined rules, constraints, and integrity constraints.
Isolation: Concurrent transactions must execute independently and not interfere with each other, even if they operate on the same data.
Durability: Once a transaction is committed, its effects must persist and remain permanent, even in the event of system failure or power outage.

ACID properties ensure database transactions’ reliability, integrity, and consistency, enabling applications to maintain data integrity and prevent corruption or inconsistent states.

 

103. What transaction isolation levels do you know?

The main transaction isolation levels in databases are:

  • Read Uncommitted: The lowest isolation level, where a transaction can read data that has been modified but not yet committed by other transactions. It can lead to dirty reads.
  • Read Committed (Default in SQL Server): A transaction can only read data that has been committed by other transactions, avoiding dirty reads. However, it is still susceptible to non-repeatable reads and phantom reads.
  • Repeatable Read: A transaction can read the same data multiple times and get consistent results, preventing non-repeatable and phantom reads.
  • Serializable: The highest isolation level, where transactions are executed as if they were happening one after another, even if they are running concurrently. This level prevents all data anomalies but may reduce concurrency and performance.

 

104. What is a query execution plan in MS SQL?

A query execution plan in Microsoft SQL Server is a strategy that the database engine generates to execute a given SQL query. It represents the sequence of operations and algorithms the query optimizer chooses to retrieve the requested data efficiently.

The query execution plan provides insights into the following:

  • The order of operations (e.g., table scans, index seeks, joins, sorts, aggregations)
  • The specific indexes and data structures used
  • The estimated cost and resource utilization (CPU, memory, I/O)
  • The data flow and data access patterns

By analyzing the query execution plan, database administrators and developers can:

  • Identify potential performance bottlenecks or inefficient operations
  • Optimize queries by modifying indexing strategies or query structures
  • Understand the reasoning behind the query optimizer's choices
  • Diagnose and troubleshoot slow-performing queries

 

105. Problem: a query is taking a long time to execute. What methods are there for diagnosing and solving this?

When a query is taking a long time to execute, there are several methods you can use to diagnose and solve the issue:

  • Analyze the Query Execution Plan: Examine the query execution plan to identify potential bottlenecks, such as inefficient index usage, costly operations (e.g., table scans), or suboptimal join strategies.
  • Check Indexing Strategy: Verify if appropriate indexes exist for the columns involved in the query predicates, joins, and sorting operations. If necessary, create new indexes or modify existing ones.
  • Review Query Structure: Analyze the query structure and consider rewriting it using more efficient constructs, such as subqueries, derived tables, or common table expressions (CTEs).
  • Check Statistics:Ensure the database statistics are up-to-date, as outdated statistics can lead to suboptimal query plans.
  • Monitor Resource Usage: Use monitoring tools to check for resource contention or bottlenecks, such as high CPU usage, memory pressure, or disk I/O issues.
  • Partition Data: If the query involves large tables, consider partitioning the data to improve query performance and enable parallel execution.
  • Optimize Database Configuration: Review database configuration settings, such as memory allocation, cost thresholds, and query optimization levels, and adjust them as needed.
  • Implement Caching: If the query involves repetitive or static data, consider implementing caching mechanisms to avoid redundant database queries.
  • Parallelize Queries: Investigate if the query can be parallelized or if the database supports parallel query execution to leverage multiple CPU cores.
  • Denormalize Data: In some cases, denormalizing data by introducing redundancy can improve query performance, but it should be carefully weighed against potential data integrity and maintenance concerns.

Often, a combination of these methods, along with profiling and iterative testing, leads to optimal query performance.

 

106. How do ORMs (Entity Framework or Entity Framework Core) translate C# code into database query language? What is used for this?

ORMs like Entity Framework and Entity Framework Core use a component called LINQ to Entities (LINQ to EF) to translate C# LINQ queries into database query language (SQL). LINQ to Entities acts as a query provider, taking the LINQ query expression and translating it into an expression tree. This expression tree is then processed by the Entity Framework query pipeline, which generates the corresponding SQL query to be executed against the database. The translation process involves analyzing the expression tree, applying optimization rules, and mapping the LINQ constructs to their SQL equivalents.

 

Parallelism

107. Why use Task.ConfigureAwait?

The Task.ConfigureAwait method controls the context-capturing behavior of await expressions in asynchronous methods. It is particularly important when writing code interacting with user interfaces, such as Windows Presentation Foundation (WPF) or Windows Forms applications.

When an asynchronous method is awaited without ConfigureAwait, the continuation (code after the await) will capture and resume on the same context (e.g., UI thread) that triggered the asynchronous operation. It can lead to performance issues and potential deadlocks if the awaited task is not related to the UI thread’s work.

By calling ConfigureAwait(false), you instruct the asynchronous method to resume its continuation on a different context (e.g., a thread pool thread) rather than capturing the original context. It helps to prevent unnecessary context switches and improves performance, especially in scenarios where the awaited task does not require the UI thread’s context.

In summary, using Task.ConfigureAwait(false) is recommended in non-UI asynchronous methods to avoid unnecessarily capturing the UI thread’s context, which can lead to performance issues and deadlocks.

 

108. For example, a web server performs a database query for an HTTP request. The server has 16 threads in total. Each HTTP request executes a database query and waits for the results, blocking the thread. Can this be optimized using .NET means?

This scenario can be optimized using asynchronous programming in .NET. Instead of blocking threads waiting for database queries, use async/await with asynchronous database operations, allowing threads to be released back to the thread pool while waiting. Also, consider increasing the maximum thread pool size if expecting high concurrency.

 

109. Why is the ThreadPool needed? Describe the mechanics: how a thread is allocated and returned to the ThreadPool.

The ThreadPool provides an efficient way to manage and reuse threads for asynchronous/parallel tasks, avoiding the overhead of manual thread creation/termination. When a task is requested, the ThreadPool allocates an available thread from its queue; if none is available and under the max limit, it creates a new thread. After executing the task, the thread is returned to the queue for reuse until an idle timeout, then terminated.

.NET Interview Questions for Senior Developers

Senior .NET interviews target candidates with 7+ years of experience. They are conversations about trade-offs more than recall. Expect deep questions on async internals, garbage collection generations, memory pressure diagnosis, and CPU-bound versus I/O-bound workload reasoning. Architecture discussions typically span microservices boundaries, idempotency, distributed transactions, message-broker semantics, and observability. A senior candidate’s value shows in how they reason about a system under failure conditions.

Senior .NET developer

General .NET Interview Questions

110. What other practices besides OOP have you used (AOP, FP, etc.)?

Besides OOP, Aspect-Oriented Programming (AOP) is used to cross-cut concerns.
Functional Programming (FP) concepts like LINQ and lambda expressions.
Event-Driven Programming for loosely coupled systems.
Reactive Programming with Reactive Extensions (Rx).
Domain-Driven Design (DDD) for modeling complex domains.

 

111. Name three of the most complex problems you’ve had to solve. How did you solve them, and how did you arrive at that solution?

Complex problems include implementing a distributed caching system (used Redis, data partitioning, failover), optimizing a data-intensive ETL process (parallelization, performance tuning), and developing a real-time messaging system (used message queues, load balancing, failover). Solutions involved researching technologies, prototyping, performance testing, and iterative design.

 

112. What is loosely-coupled code? How is it better than tightly-coupled code? How would you achieve loose coupling?

Loosely-coupled code has minimal dependencies between components, enabling independent development and evolution. It’s better than tightly-coupled code, which is harder to maintain and change. Achieve loose coupling through abstractions (interfaces), dependency injection, event-driven communication, and modular design.

Static classes deserve a separate note. They can increase coupling by introducing global state and implicit dependencies across the codebase. Use them sparingly, mostly for stateless utility methods.

 

113. How can you measure code performance? Does the act of measuring affect performance?

Code performance can be measured using profiling tools, benchmarking frameworks, and performance counters. The act of measuring can affect performance due to instrumentation overhead.

 

114. What are multi-stage builds in Docker, and how do they work?

Multi-stage builds in Docker are a feature that allows you to build your Docker image in multiple stages. It is useful for reducing the final image size by only including the necessary files and dependencies. Each stage can use a different base image, and you can copy artifacts from one stage to the next.

 

115. How can you tell when a piece of code is consuming a lot of memory or running slowly? What can be a bottleneck in different cases? What are ways to reduce memory usage and memory traffic?

You can use profiling tools like memory and CPU profilers to identify code that consumes a lot of memory or runs slowly. Potential bottlenecks could be CPU-bound tasks, I/O-bound tasks, or memory-intensive operations. You can optimize data structures, limit allocations, and use techniques like memory pooling to reduce memory usage. To reduce memory traffic, you can improve cache utilization, minimize data copying, and optimize memory access patterns.

 

116. How would you implement a cross-cutting concern (e.g., logging, validation, transactions)?

You can use design patterns like the Decorator or Aspect-Oriented Programming (AOP) approach to implement cross-cutting concerns like logging, validation, or transactions.

 

117. Tell me about the REST Maturity Model.

The REST Maturity Model is a framework for evaluating the level of “RESTfulness” in an API. It has four levels: Level 0 (the most basic), Level 1 (resource-oriented), Level 2 (HTTP verbs), and Level 3 (hypermedia controls).

 

118. What are CPU-bound and IO-bound tasks?

CPU-bound tasks, such as mathematical computations, primarily use the CPU. while
I/O-bound tasks involve waiting for external resources, such as reading from a database or making network requests.

 

119. What is Native AOT in .NET, and when would you reach for it?

Native Ahead-of-Time (Native AOT) compilation, introduced in .NET 7 and matured through .NET 10, compiles a .NET application into a single self-contained native binary at publish time. No IL. No JIT compiler at runtime. No managed assembly loading from disk during startup.

The result is a dramatically smaller deployment footprint, faster cold start (sub-100ms for many services versus several seconds with the JIT), plus lower steady-state memory use. Those properties make Native AOT a strong fit for serverless functions, container workloads where startup latency matters, command-line tools, and lightweight microservices that do not rely on dynamic features.

The trade-offs are real. Native AOT disables dynamic code generation (System.Reflection.Emit), runtime assembly loading (Assembly.LoadFrom), plus certain reflection paths. Libraries that depend on these (older ORMs, some serializers, plus older IoC containers) need AOT-compatible variants. Build time is longer, and the published binary targets a specific platform.

As of .NET 10, the .NET ecosystem has broad AOT compatibility. ASP.NET Core minimal APIs, System.Text.Json source-generation mode, plus EF Core with the compiled model workflow all work under Native AOT. Reach for Native AOT when startup time and memory footprint are first-class requirements. Stick with the standard JIT for general-purpose services where reflection-heavy libraries dominate.

 

120. How does async/await work (in detail)? Why can’t you use async void methods?

Async/await in programming languages like C# and JavaScript allows developers to write asynchronous code that appears synchronous. The await keyword pauses the execution of the current method until the asynchronous operation is complete, allowing the thread to be used for other tasks in the meantime. Async void methods are not recommended because they can be difficult to handle errors and exceptions.

 

ASP.NET Core and Tooling Interview Questions

121. How does the lock statement work? Can you use structs inside a lock expression?

The lock statement in C# acquires a mutual exclusion lock on a given object, ensuring that only one thread can execute the code within the lock block at a time. Structs can be used inside a lock expression, but it’s generally not recommended as structs are value types and can lead to unexpected behavior.

 

122. What are Expression Trees?

Expression Trees represent code in a tree-like data structure, where each node represents a particular code construct, such as a method call, a variable, or an operator. They are used in LINQ and other advanced .NET features to analyze and manipulate code at runtime.

 

123. How does the Garbage Collector work (in detail)? Why are there three generations in GC, not five, ten, or two?

The .NET Garbage Collector (GC) automatically reclaims memory occupied by objects no longer in use. GC uses a generational approach, with three generations (0, 1, and 2), to optimize performance. Newer objects are placed in generation 0, and if they survive multiple collections, they are promoted to higher generations. This approach collects the most frequently used, short-lived objects more often.

 

124. How would you set up tracing for Web API services?

You can use tools like Application Insights or Elastic APM to set up tracing for Web API services. These provide out-of-the-box integration with ASP.NET Core and allow you to collect and analyze various telemetry data.

 

125. How can you configure secret storage for .NET Core applications on developer machines and production environments?

For secret storage in .NET Core applications, you can use solutions like Azure Key Vault, AWS Secrets Manager, or HashiCorp Vault. These provide a secure way to store and manage sensitive information in development and production environments, such as connection strings and API keys.

 

126. How would you organize the CI/CD process for .NET Core services to deploy them to a cloud infrastructure?

To organize the CI/CD process for .NET Core services, you can use tools like Azure DevOps, GitHub Actions, or Jenkins. These allow you to set up automated build, test, and deployment pipelines, ensuring consistent and reliable deployments to your cloud infrastructure.

 

127. How do you enable CORS in ASP.NET Core?

In ASP.NET Core, enable CORS in Program.cs by registering a named or default policy with the DI container and then applying it in the middleware pipeline:

builder.Services.AddCors(options =>
{
options.AddPolicy(“AllowFrontend”, policy =>
policy.WithOrigins(“https://app.example.com”)
.AllowAnyHeader()
.AllowAnyMethod());
});

// later in the pipeline
app.UseCors(“AllowFrontend”);

The policy specifies which origins can access the API and what headers and HTTP methods they may use. Apply policies globally with UseCors or per-endpoint with the [EnableCors] and [DisableCors] attributes.

 

Data Types, Collections, and Data Structures

128. How are generics implemented?

The CLR reifies .NET generics at runtime. It keeps generic type information through compilation and execution. The compiler emits IL that retains the generic type parameters in metadata. At runtime, the CLR specializes the generic type per concrete instantiation. For value-type instantiations (List<int>, List<double>), the JIT generates separate native code per type for maximum performance. For reference-type instantiations (List<string>, List<Customer>), the CLR shares a single generic implementation because all references are the same size.

Generic type information stays available from compilation through runtime. You can reflect on typeof(List<int>) at runtime and recover the type argument. You can construct closed generic types dynamically via MakeGenericType. This is the main implementation difference between .NET and the JVM, where the JVM erases generic type information after the compile step (the Java type erasure model).

 

129. How do you create your immutable type?

To create your immutable type, you can make the class sealed and ensure that all its properties are read-only. You can also make the class’s constructor private and provide a static factory method to create instances of the class.

 

130. How does IEnumerable<T> work (in detail)?

IEnumerable<T> is a simple interface that defines a single method, GetEnumerator(), which returns an IEnumerator<T>. This interface allows you to iterate over a collection of items without exposing the underlying data structure.

 

131. What algorithm does the STACK collection use?

The STACK collection uses a Last-In-First-Out (LIFO) algorithm, where elements are added and removed from the top of the stack.

 

132. What is the difference between Span<T> and Memory<T>, and when should you use each?

Span<T> and Memory<T> both represent a contiguous region of memory without copying the underlying data. Both let you slice into a buffer (managed or unmanaged) and work with it via a uniform API. Both also help you avoid allocations. The difference between the two is where each can live in memory.

Span<T> is a ref struct. It can point to memory on the managed heap, on the stack via stackalloc, plus in unmanaged regions, and the CLR confines it to the stack itself. A Span<T> cannot be a field of a regular class. You cannot capture it in a lambda or hold it across an await boundary. That stack-only constraint is exactly what makes Span<T> safe and fast for synchronous, hot-path code.

Memory<T> is a regular struct. You can store it on the heap as a class field, capture it in closures, plus pass it through async methods. The trade-off is a slightly higher runtime cost and an extra step: you typically convert to a Span<T> via memory.Span for the actual read or write.

Use Span<T> for synchronous hot paths where you slice into a buffer for parsing or serialization work. Use Memory<T> when the buffer must survive an await or live as a class field, plus when an asynchronous API needs to consume it.

 

133. How do interfaces differ from abstract classes? In what cases would you use one or the other?

The main difference between interfaces and abstract classes is that interfaces can only define method signatures, properties, events, and indexers. At the same time, abstract classes can include method implementations, fields, and constructors. Interfaces are generally used to define contracts or APIs, while abstract classes are used to provide a base implementation for related types.

 

Databases

134. How do databases store data?

Databases store data in a structured way, typically in tables with rows and columns. The specific storage mechanisms vary between different database management systems (DBMS). However, they generally use a combination of in-memory caching, disk-based storage, and indexing to optimize performance.

 

135. When and which databases are better to use?

The choice of database depends on factors like the data model, scalability requirements, performance needs, and the type of queries the application will perform. RDBMS are well-suited for applications with structured data and complex relationships. In contrast, NoSQL databases excel at handling unstructured data and high-volume, high-velocity workloads.

 

136. When and which transaction isolation levels can you use?

Transaction isolation levels determine how much interference can occur between concurrent transactions. The most common levels are READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ, and SERIALIZABLE, each with different trade-offs between consistency and concurrency.

 

137. How are the ACID principles implemented in popular RDBMSs (SQL Server, PostgreSQL, etc.)?

ACID (Atomicity, Consistency, Isolation, Durability) principles are implemented in RDBMS through features like transaction management, locking mechanisms, and logging/recovery processes.

 

138. Describe potential issues you know of related to parallel database queries.

Potential issues with parallel database queries include deadlocks, race conditions, and increased contention for shared resources. These issues can lead to performance degradation or data consistency issues.

 

139. What is HybridCache in .NET 9+, and how does it differ from IMemoryCache and IDistributedCache?

HybridCache, introduced as a Microsoft.Extensions.Caching abstraction in .NET 9 and stabilized in .NET 10, combines an in-process L1 cache with a distributed L2 cache behind a single API. Where you previously wrote layered code over IMemoryCache for local lookups and IDistributedCache for the shared backing store, HybridCache handles the two-tier lookup, the serialization, plus the cache invalidation behind one method call.

The typical call is cache.GetOrCreateAsync(key, factory, options). HybridCache checks the L1 in-process cache first. It falls back to the L2 distributed cache (such as Redis or SQL Server) when L1 misses, and only invokes the factory when both miss. It also coordinates concurrent requests for the same key so the factory runs once per process even under load. That stampede protection is the part teams most often write incorrectly when building their own two-tier cache.

HybridCache is the right default for new .NET services that need both local and shared caching. Use IMemoryCache alone for purely in-process state that does not need to survive process restarts or appear in other instances. Use IDistributedCache alone when local memory cannot hold a meaningful working set, though that case is rare in practice.

 

Microservices

140. What problem do microservices solve?

Microservices solve the complexity problem in large, monolithic applications by breaking them down into smaller, independent services that can be developed, deployed, and scaled separately.

 

141. What are the ways microservices can communicate?

Microservices can communicate using various inter-service communication patterns, such as synchronous HTTP/REST, asynchronous messaging (e.g., queues, event buses), or a hybrid approach.

 

142. Discuss implementation options for distributed transactions in microservices.

Distributed transactions in microservices can be implemented using techniques like the Saga pattern. It coordinates multiple local transactions to achieve eventual consistency or by using a distributed transaction coordinator (DTC) like the one provided by SQL Server.

 

143. What is a circuit breaker?

A circuit breaker is a design pattern that helps manage failures in distributed systems by preventing cascading failures and providing fallback options when a downstream service is unavailable.

 

144. How would you debug a system composed of multiple microservices to trace the full request processing path?

To debug a microservices-based system, you can use distributed tracing tools like Jaeger or Zipkin, which allow you to trace the full request processing path across multiple services.

 

145. What are message brokers? What are at-least-once, at-most-once semantics? Are there any brokers that guarantee exactly-once semantics?

Message brokers like RabbitMQ, Apache Kafka, or Azure Service Bus facilitate asynchronous communication between microservices. At-least-once semantics ensure that a message is delivered at least once, while at-most-once semantics guarantee that a message is delivered at most once. Exactly-once semantics, which ensures a message is delivered exactly once, can be achieved using techniques like idempotency.

 

146. How should the broker client code work depending on the chosen semantics?

Depending on the chosen message delivery semantics, the broker client code should appropriately handle retries, timeouts, and error handling.

 

MS Azure Interview Questions

147. What is .NET Aspire, and what problems does it solve?

.NET Aspire is Microsoft’s cloud-native application stack for .NET. It went GA in November 2024 with .NET 9, and the current release is Aspire 13.1 paired with .NET 10. Aspire is not a runtime or a framework. It is an orchestration layer plus a curated set of integrations that simplifies building, running, plus observing distributed .NET applications.

An Aspire solution adds an AppHost project that wires together the services, databases, caches, message brokers, and external resources your application depends on. On dotnet run, Aspire launches every component locally with consistent configuration, OpenTelemetry traces, metrics, logs, plus a built-in dashboard for inspecting the running topology. The same composition file describes the production deployment with adapters for Kubernetes, Azure Container Apps, plus other cloud targets.

Aspire solves the friction of local distributed development. Before Aspire, a developer running a microservices solution juggled Docker Compose, environment files, ad-hoc telemetry setup, and per-service onboarding. Aspire collapses that into typed C# composition with full IDE support and a unified observability story.

 

148. What are the characteristics and limitations of Azure Table Storage?

Azure Table Storage is a NoSQL key-value store with high availability and durability, plus scalability. Notable characteristics include eventual consistency. Query capability remains narrower than what relational databases offer. Maximum storage is 5 PiB per general-purpose v2 storage account. Table Storage is well-suited for storing large amounts of semi-structured data such as user profiles, device information, plus log data.

For workloads that outgrow Table Storage limits, Azure Cosmos DB exposes a Table API with global distribution and tunable consistency, plus higher throughput.

 

149. How do you deal with the cold start problem in Azure Functions?

The cold start problem in Azure Functions refers to the delay in function execution when the runtime needs to spin up a new instance to handle a request. To mitigate this, you can use strategies like keeping the function app warm, using a consumption plan with a pre-warmed instance, or leveraging a dedicated App Service plan.

 

150. What’s the difference between queues and topics in Azure Service Bus?

In Azure Service Bus, queues deliver simple first-in, first-out (FIFO) message. At the same time, topics enable a publish-subscribe model where multiple subscriber rules can be defined to filter messages. Queues are useful for one-to-one communication, while topics are better suited for one-to-many scenarios.

Tips for Hiring Managers

01
Ask targeted questions
Tailor your .NET interview questions to the specific role's needs. A team building an ASP.NET Core API needs different signals from one running a legacy WebForms migration. Use the tier breakdown above as a starting point. Adapt the questions to fit the specific role.
02
Evaluate problem-solving over memorization
Ask candidates to solve coding challenges using .NET. Observe their approach and logic. Multiple interviews are ideal, including a technical screening and pair programming with experienced developers. Administer timed coding tests mimicking real scenarios. Evaluate candidates' proficiency in writing clean, well-structured, and maintainable .NET code.
03
Test communication alongside code
Getting things done smoothly in development requires everyone to be on the same page. Include questions that gauge a candidate's ability to explain technical concepts clearly.
04
Provide a positive interview experience:
Set a welcoming tone for the interview. This way, candidates can showcase skills comfortably and ask questions freely.

Tips for Candidates

01
Research the company:
Research the company's website ("About Us", "Our Work/Projects"), news, and LinkedIn page. Note their projects, products, and challenges. Understand their mission, culture, and values. Tailor your background to their needs. Prepare relevant experience examples that showcase fit.
02
Practice your answers:
Prepare for common .NET interview questions by rehearsing your responses beforehand.
03
Highlight your problem-solving skills:
Don't just memorize answers. Demonstrate your ability to think critically to land a job at .NET development company.
04
Ask insightful questions:
Such an approach shows genuine interest in the role and the company. Prepare thoughtful questions about the team, projects, or the technology stack they use.

Summing up

Acing a .NET interview requires a collaborative effort. Candidates need to demonstrate their technical expertise, problem-solving skills, and passion for development. However, for hiring managers, a successful interview goes beyond a list of .NET interview questions. Evaluate communication skills and cultural fit, ensuring the candidate thrives in a team. Give coding challenges using .NET in interviews. Observe their approaches and logic.

Thankfully, valuable solutions are available to simplify this process. If you want to skip the hassle of screening and interviewing, contact us. Here at DOIT Software, we have a smooth process for hiring top .NET developers. We can provide you with the first CVs in a few days.

Frequently Asked Questions

Planning to hire .NET developers?

Get a consultation and start building your dream team ASAP.

Request CVs

How do I prepare for a .NET interview?

Preparing for a .NET interview comes down to three habits. Start with the fundamentals: C# language semantics, the CLR’s memory model and garbage collector, value versus reference types, plus modern language features. Records and primary constructors are useful to know. Async/await is non-negotiable. Then practice the question types above out loud.

Explaining how generics work or why IEnumerable differs from IQueryable reads cleanly only after you have said it a few times. Finally, sharpen your problem-solving skills; interviewers love to see how you think through coding challenges.

How do I prepare for a senior .NET developer interview?

Acing a senior .NET interview hinges on three things: 1) Level up your skills with advanced topics like ASP.NET Core MVC and design patterns. 2) Showcase your experience with real-world projects, highlighting challenges and impact. 3) Think leader – be ready to discuss code reviews, knowledge sharing, and building a strong team.

What is .NET in C# interview questions?

.NET is Microsoft’s open-source, cross-platform development platform. The unified .NET family (currently .NET 10 LTS, released November 2025) supports C# 14 and covers web, cloud, mobile, desktop, and high-performance services.

C# code compiles to Intermediate Language (IL) and runs on the Common Language Runtime (CLR), which handles memory management, type safety, exception handling, and security. The platform interoperates with libraries written in F# and Visual Basic and supports both JIT and ahead-of-time (AOT) compilation. The legacy .NET Framework 4.x stack is Windows-only and in maintenance.

What are the most important .NET topics to study in 2026?

Modern language and runtime cover records, primary constructors, collection expressions, the C# 14 field keyword, Span<T> and Memory<T>, async streams (IAsyncEnumerable), and pattern matching. Modern platform covers minimal APIs in ASP.NET Core, Native AOT, .NET Aspire for cloud-native composition, HybridCache for two-tier caching, and Output Caching middleware.

Architecture and distributed systems cover idempotency patterns, message broker semantics (at-least-once versus at-most-once), distributed tracing with OpenTelemetry, circuit breakers, and the Saga pattern. Interviewers at scaleups are increasingly testing whether candidates have moved past the .NET Framework 4.x mental model into the unified .NET 8+ era.

Vitaly DOIT Software
Vitalii Makhov
CEO @ DOIT Software
Please rate the article
  • star empty star full
  • star empty star full
  • star empty star full
  • star empty star full
  • star empty star full
/5
Based on reviews
Read More About