Introduction
Are you ready to take your career in software development to new heights and crush your coming rounds? The .NET platform continues to be one of the leading ecosystems for building enterprise applications, ensuring that .NET developers are always in high demand. With so many people clamoring for your skills, you’ll need a solid understanding of architectural and coding fundamentals alike. Here, we’ve compiled the best basic and coding Dot Net Interview questions and answers, which will help ensure success in your coming interviews. Interested in learning everything there is to know about .NET? Check out our complete Dot Net Course Syllabus today!
Dot Net Basic Interview Questions and Answers
Here are some basic Dot Net interview questions and answers.
1. What are the distinctions between the .NET Framework, .NET Core, and .NET 5+?
- The .NET Framework is an outdated and Windows-based platform for developing desktop and web applications.
- .NET Core came as an open-source and cross-platform alternative.
- With the release of .NET 5 and beyond (which includes .NET 6, 7, and 8), Microsoft decided to merge all previous iterations into one platform by stripping off “Core” from its name.
The new .NET is a single and cross-platform environment that supports all workloads.
2. Discuss the functions of the Common Language Runtime (CLR).
The CLR is the virtual machine portion of the .NET Framework designed to execute .NET applications. It works by compiling the source code into intermediate language (IL), which then gets translated into machine language through JIT compilation.
Moreover, the CLR manages important tasks such as memory management, garbage collection, exception handling, and threads.
3. Explain Garbage Collection (GC) in .NET
The Garbage Collection process in the .NET framework helps in managing the memory by reclaiming memory used by dead objects. The heap in .NET can be categorized into three generations, namely, Generation 0 for temporary objects, Generation 1 as a buffer, and Generation 2 as long-lived objects.
Whenever the generation is full, the GC performs its function by collecting references of unused objects, releasing their memory, and compacting the other objects.
4. Managed Code vs. Unmanaged Code
- Managed code consists of code that uses a high-level programming language such as C# and is executed within the CLR (Common Language Runtime), which provides additional benefits such as automatic memory management via garbage collection and type safety.
- On the contrary, unmanaged code is converted to machine code before running and hence runs outside the CLR runtime environment.
5. Define the terms value types and reference types.
- Value types hold the actual value in the stack memory, and copying is done when values are assigned. Primitive and struct fall under value types.
- Reference types contain the memory address of the actual value kept in the heap in the stack. Class, string, and array are examples of reference types.
6. What is boxing and unboxing in the .NET Framework?
- Boxing is an automatic conversion process where the value type is automatically converted to the reference type (Object). It is accomplished by creating a new instance on the heap memory and then copying the value.
- Unboxing is the reverse operation of boxing where the value is extracted from the object explicitly. Both operations have performance overheads.
7. Explain the difference between String and StringBuilder.
- The String type is immutable, implying that any change to it, like adding a string to it, results in the creation of a completely new String object, leaving the old object up for garbage collection.
- The StringBuilder, on the other hand, is mutable because it reserves a buffer space, which enables manipulation, appending, and deletion of content from the reserved memory space.
8. Define Abstract classes and Interfaces and describe their differences.
- An abstract class is a semi-complete class design that includes implemented methods, state fields, and access modifiers, thus making it possible for one class to extend only a single base class.
- An interface is strictly an agreement that defines methods alone; state fields cannot be included in it (default methods in modern C#). A class can, however, implement multiple interfaces.
9. What is DI, and how is it handled in .NET Core?
Dependency Injection is a pattern used to implement IoC between classes and their respective dependencies and helps make them loosely coupled.
.NET Core provides a native first-class IoC container that provides three different lifetimes for services: transient lifetime (new object for each request), scoped lifetime (single object for one client connection/request), and singleton lifetime (single object for the entire application).
10. Describe the difference between Middleware and Filters in ASP.NET Core?
- The middleware is present in the global request pipeline of the application. It processes every incoming HTTP request and its corresponding response (e.g., logging, authentication, CORS).
- The filters work inside the MVC action execution lifecycle. They work only when routing selects some action method and give developers a way to write code for action-based security, validation, or exceptions.
Dot Net Coding Interview Questions and Answers
1. Write a program to reverse a string without using built-in reverse methods.
using System;
class Program {
static void Main() {
string input = “DotNet”;
char[] charArray = input.ToCharArray();
int left = 0, right = input.Length – 1;
while (left < right) {
char temp = charArray[left];
charArray[left] = charArray[right];
charArray[right] = temp;
left++;
right–;
}
Console.WriteLine(new string(charArray)); // Output: tentoD
}
}
2. Implement a Singleton pattern in C# that is thread-safe.
using System;
public sealed class Singleton {
private static readonly Lazy<Singleton> _instance =
new Lazy<Singleton>(() => new Singleton());
public static Singleton Instance => _instance.Value;
private Singleton() { } // Prevents direct instantiation
}
3. Use LINQ to find the second-highest number in an integer array.
using System;
using System.Linq;
class Program {
static void Main() {
int[] numbers = { 5, 12, 3, 9, 12, 7, 11 };
int secondHighest = numbers.Distinct()
.OrderByDescending(n => n)
.Skip(1)
.FirstOrDefault();
Console.WriteLine(secondHighest); // Output: 11
}
}
4. Write a C# program to check if a string is a palindrome.
using System;
class Program {
static void Main() {
string str = “radar”;
bool isPalindrome = true;
int len = str.Length;
for (int i = 0; i < len / 2; i++) {
if (str[i] != str[len – 1 – i]) {
isPalindrome = false;
break;
}
}
Console.WriteLine(isPalindrome); // Output: True
}
}
5. Demonstrate how to read a file asynchronously using async and await.
using System;
using System.IO;
using System.Threading.Tasks;
class Program {
static async Task Main() {
string path = “sample.txt”;
await File.WriteAllTextAsync(path, “Hello .NET Developer!”);
string content = await File.ReadAllTextAsync(path);
Console.WriteLine(content);
}
}
6. Write a program to find the occurrence of each character in a string.
using System;
using System.Collections.Generic;
class Program {
static void Main() {
string text = “hello”;
Dictionary<char, int> charCounts = new Dictionary<char, int>();
foreach (char c in text) {
if (charCounts.ContainsKey(c)) charCounts[c]++;
else charCounts[c] = 1;
}
foreach (var pair in charCounts) {
Console.WriteLine($”{pair.Key}: {pair.Value}”);
}
}
}
7. Implement an Extension Method in C# to count words in a string.
using System;
public static class StringExtensions {
public static int WordCount(this string str) {
if (string.IsNullOrWhiteSpace(str)) return 0;
return str.Split(new[] { ‘ ‘, ‘\r’, ‘\n’ }, StringSplitOptions.RemoveEmptyEntries).Length;
}
}
class Program {
static void Main() {
string sentence = “Mastering .NET development takes practice.”;
Console.WriteLine(sentence.WordCount()); // Output: 5
}
}
8. Write a C# code snippet to demonstrate the use of yield return.
using System;
using System.Collections.Generic;
class Program {
static IEnumerable<int> GetEvenNumbers(int max) {
for (int i = 1; i <= max; i++) {
if (i % 2 == 0) yield return i; // State is preserved between calls
}
}
static void Main() {
foreach (int num in GetEvenNumbers(6)) {
Console.Write(num + ” “); // Output: 2 4 6
}
}
}
9. Write a generic method to swap two values of any data type.
using System;
class Program {
static void Swap<T>(ref T a, ref T b) {
T temp = a;
a = b;
b = temp;
}
static void Main() {
int x = 10, y = 20;
Swap(ref x, ref y);
Console.WriteLine($”x: {x}, y: {y}”); // Output: x: 20, y: 10
}
}
10. Create a custom Exception class and demonstrate how to throw/catch it.
using System;
public class InvalidAgeException : Exception {
public InvalidAgeException(string message) : base(message) { }
}
class Program {
static void CheckAge(int age) {
if (age < 18) throw new InvalidAgeException(“Access denied: Under 18.”);
}
static void Main() {
try {
CheckAge(15);
} catch (InvalidAgeException ex) {
Console.WriteLine(ex.Message); // Output: Access denied: Under 18.
}
}
}
11. Explain Memory Management Concepts — Span<T>, Memory<T>, and Low-Allocation Architecture
Core Principles: Span<T> and Memory<T> are used by .NET to provide contiguous typed memory without requiring garbage collection allocations. Span<T> is a stack-allocated ref struct that provides an interpretation of a memory segment on the managed heap, the native stack, or the native heap. Since it is a ref struct, it cannot be boxed, placed within regular classes, or used across async boundaries. Memory<T> acts as the factory of the heap that creates Span<T> handles temporarily.
Trade-offs: High Throughput Microservices process multiple gigabytes of JSON or Streaming Buffers per second. String.Substring() allocations result in character array copy operations to the heap, thereby triggering huge Garbage Collection pressure on Generation 0. On the other hand, ReadOnlySpan<char> extracts slices from streams quickly using memory pointers without any allocation.
Code Example:
using System;
public class HighPerformanceParser
{
// High-performance string parsing using Zero-Allocation Slicing via Span
public static ReadOnlySpan<char> ExtractPayloadId(string dynamicPayload)
{
if (string.IsNullOrEmpty(dynamicPayload)) return ReadOnlySpan<char>.Empty;
ReadOnlySpan<char> view = dynamicPayload.AsSpan();
int idStartIndex = view.IndexOf(‘:’);
if (idStartIndex == -1) return ReadOnlySpan<char>.Empty;
// Zero allocations occur during the slice operations
return view.Slice(idStartIndex + 1);
}
}
12. Explain Advanced Garbage Collection Settings — Server Garbage Collector (GC) VS Workstation GC and LOH Optimization Techniques
Configuring the GC Engine: Selecting either Workstation or Server GC results in a different thread topology and throughput capabilities in the context of intensive operating system operations.
LOH Optimization Parameters: Any object size above 85,000 bytes skips the process of generation compaction and goes directly into the LOH. The LOH cannot undergo compacting because of the overhead cost associated with pointer remapping. Senior engineers overcome this problem through reusing of memory segments via ArrayPool<T>, memory pinning, or altering compaction flags in the runtime environment.
| Optimization Vector | Workstation GC Mode | Server GC Mode |
| Thread Architecture | Runs on the calling application thread | Spawns dedicated GC threads per CPU core |
| Concurrency Design | Prioritizes UI/Client app UI responsiveness | Prioritizes overall system processing throughput |
| LOH Compaction Behavior | Sweeps without shifting memory addresses | Configurable via GCSettings.LargeObjectHeapCompactionMode |
Code Example:
using System;
using System.Runtime;
public class LargeObjectOptimizer
{
public static void OptimizeRuntimeHeaps()
{
// Forces the Garbage Collector to compact the LOH during the subsequent full collection sweep
GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
GC.Collect(2, GCCollectionMode.Forced, blocking: true, compacting: true);
}
}
13. Explain Advanced Asynchronous Pipeline Construction – Task, ValueTask, and Threadpool Starvation
Task allocation involves the creation of an object context on the managed heap. In case a method executes synchronously or pulls the required information from the currently running cache, Task instance allocation will cause additional memory costs.
Using ValueTask as the return type results in wrapping either the result or Task, thus resulting in zero-allocation for the synchronous execution of an operation.
ThreadPool Starvation and Synchronous Calls over Async Operations: Mixing async wait calls within synchronous structures using the .Wait() or .Result() calls make the thread pool executing the current task stop awaiting the return of the inner async call. This becomes a serious issue if the traffic becomes too heavy.
Code Example:
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
public class DistributedCacheService
{
private readonly Dictionary<string, string> _inMemoryCache = new();
// Zero allocation runtime performance for synchronous in-memory cache operations
public ValueTask<string?> RetrieveDataAsync(string cacheKey)
{
if (_inMemoryCache.TryGetValue(cacheKey, out var fastValue))
{
return new ValueTask<string?>(fastValue); // Synchronous completion: Zero allocations
}
return new ValueTask<string?>(FetchFromRemoteDatabaseAsync(cacheKey)); // Asynchronous fallback
}
private async Task<string> FetchFromRemoteDatabaseAsync(string cacheKey)
{
await Task.Delay(50); // Simulate asynchronous database latency
return “Remote_Payload_Data”;
}
}
14. Explain Parallel Synchronization Semantics – Locks, Monitor, SemaphoreSlim, and Lock-Free Interlocked Mutexes
- Synchronization Primitives: Scaling for concurrency needs thread isolation mechanisms that match the particular access contention semantics. The basic lock structure is a wrapper around Monitor.Enter and Monitor.Exit, using compiler tricks. But locks are exclusive and stop threads entirely from an operating system perspective, hindering system throughput.
- Lockless Execution: In cases where the operations do not need any locking (such as updating state or aggregate math), the lock-free implementation uses Interlocked and leverages CPU instructions. If planning on scheduling asynchronous operations within application tiers, SemaphoreSlim should be used instead.
Code Example:
using System;
using System.Threading;
public class HighThroughputCounter
{
private int _atomicTotalRequestCount;
// Lockless memory mutation using CPU atomic operational registers
public void IncrementTotalRequests()
{
// Thread-safe modification achieved without OS-level thread blockades
Interlocked.Increment(ref _atomicTotalRequestCount);
}
public int GetTotalRequests() => Volatile.Read(ref _atomicTotalRequestCount);
}
15. Explain Reflection vs. Source Generators.
- Reflection: Reflection operates on metadata during the program execution phase, which could impact the performance since type lookup and reading of metadata may cause some delay. Moreover, the process of reflection makes impossible to perform tree-shaking optimization, therefore making the process of using Native AOT complicated.
- Source Generators: Source generators compile the code generated from boilerplate code during the building process. It helps to eliminate metadata overhead, reduce the startup delays for the application and ensures that your application runs under Native AOT optimization.
Code Example:
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
[JsonSerializable(typeof(InventoryPayload))]
public partial class SourceGeneratedContext : JsonSerializerContext
{
// Source generator automatically builds metadata compilation trees during the build step
}
public class InventoryPayload { public string Sku { get; set; } = “”; public int StockLevel { get; set; } }
public class NativeAotSerializer
{
public string GeneratePayloadText(InventoryPayload payload)
{
// Zero reflection execution achieved via source-generated metadata contexts
return JsonSerializer.Serialize(payload, SourceGeneratedContext.Default.InventoryPayload);
}
}
Conclusion
Passing a .NET technical interview will be a combination of knowledge about the basic principles of architecture and good coding logic skills. By knowing some basic things, such as CLR execution, dynamics of memory management, and the new C# architecture, you can distinguish yourself among other candidates for the job. Practical experience in coding and architecture is what will make you look like an experienced developer.
Enhance your professional skills and create enterprise-level applications using our course. Join our Dot Net Course in Chennai today!


