.NET Interview Questions and Answers: Complete Guide for 2025

January 22, 2025.NET • C# • Interview • Software Development

.NET Core development and interview preparation

Loading...

Loading...

Preparing for a .NET interview requires a solid understanding of core concepts, advanced features, and real-world application patterns. This comprehensive guide covers essential .NET interview questions that you're likely to encounter, from fundamental concepts to advanced scenarios. Whether you're interviewing for a junior developer position or a senior architect role, this guide will help you demonstrate your expertise in .NET development.

Core .NET Concepts

What is .NET and How Does It Differ from .NET Framework?

.NET is a free, open-source, cross-platform framework for building modern applications. The key differences between .NET (formerly .NET Core) and .NET Framework include:

Understanding the Common Language Runtime (CLR)

The CLR is the execution engine of .NET that provides services like memory management, type safety, exception handling, and garbage collection. When you compile C# code, it's converted to Intermediate Language (IL), which the CLR then compiles to native machine code using Just-In-Time (JIT) compilation.

// Example: Understanding value types vs reference types
public class ReferenceTypeExample
{
    public int Value { get; set; }
}

public struct ValueTypeExample
{
    public int Value { get; set; }
}

// Value types are stored on the stack
ValueTypeExample vt = new ValueTypeExample { Value = 10 };

// Reference types are stored on the heap
ReferenceTypeExample rt = new ReferenceTypeExample { Value = 10 };

Garbage Collection in .NET

.NET uses a generational garbage collector with three generations (0, 1, 2). New objects start in Generation 0. Objects that survive a collection are promoted to the next generation. This design optimizes for the fact that most objects are short-lived.

Interview Question: "How does garbage collection work in .NET?"

Answer: The GC uses a mark-and-sweep algorithm. It identifies reachable objects starting from root references (static fields, local variables, CPU registers), marks them, and then sweeps unreachable objects. The GC can be triggered manually with GC.Collect(), but this is generally discouraged except in specific scenarios.

Advanced .NET Topics

Dependency Injection and IoC Containers

Dependency Injection (DI) is a design pattern that implements Inversion of Control (IoC) to achieve loose coupling. .NET provides built-in DI support through the Microsoft.Extensions.DependencyInjection package.

// Service registration
public void ConfigureServices(IServiceCollection services)
{
    // Transient: New instance every time
    services.AddTransient<IEmailService, EmailService>();
    
    // Scoped: One instance per HTTP request
    services.AddScoped<IUserRepository, UserRepository>();
    
    // Singleton: One instance for the application lifetime
    services.AddSingleton<ICacheService, CacheService>();
}

// Constructor injection
public class UserController
{
    private readonly IUserRepository _userRepository;
    
    public UserController(IUserRepository userRepository)
    {
        _userRepository = userRepository;
    }
}

Entity Framework Core: Code-First vs Database-First

Entity Framework Core supports multiple approaches to data modeling:

// Code-First example
public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
    public List<Post> Posts { get; set; } = new();
}

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
    public int BlogId { get; set; }
    public Blog Blog { get; set; }
}

// DbContext configuration
public class BloggingContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    public DbSet<Post> Posts { get; set; }
    
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>()
            .HasMany(b => b.Posts)
            .WithOne(p => p.Blog)
            .HasForeignKey(p => p.BlogId);
    }
}

Coding Challenges and Examples

Implementing a Thread-Safe Singleton Pattern

A common interview question involves implementing a thread-safe singleton. Here's the recommended approach using Lazy<T>:

public class ThreadSafeSingleton
{
    private static readonly Lazy<ThreadSafeSingleton> _instance = 
        new Lazy<ThreadSafeSingleton>(() => new ThreadSafeSingleton());
    
    private ThreadSafeSingleton() { }
    
    public static ThreadSafeSingleton Instance => _instance.Value;
    
    public void DoWork()
    {
        // Singleton implementation
    }
}

// Usage
var singleton = ThreadSafeSingleton.Instance;
singleton.DoWork();

LINQ Performance Considerations

Understanding when to use LINQ methods and their performance implications is crucial:

// Deferred execution - query not executed until enumeration
var query = numbers.Where(n => n > 10).Select(n => n * 2);

// Immediate execution with ToList()
var results = numbers.Where(n => n > 10).Select(n => n * 2).ToList();

// Performance tip: Use FirstOrDefault() instead of Where().FirstOrDefault()
// Bad: O(n) - iterates entire collection
var bad = numbers.Where(n => n > 10).FirstOrDefault();

// Good: O(n) but stops at first match
var good = numbers.FirstOrDefault(n => n > 10);

Real-World Architectural Patterns

Repository Pattern Implementation

The Repository pattern abstracts data access logic and provides a cleaner separation of concerns:

public interface IRepository<T> where T : class
{
    Task<T> GetByIdAsync(int id);
    Task<IEnumerable<T>> GetAllAsync();
    Task AddAsync(T entity);
    Task UpdateAsync(T entity);
    Task DeleteAsync(int id);
}

public class Repository<T> : IRepository<T> where T : class
{
    protected readonly DbContext _context;
    protected readonly DbSet<T> _dbSet;
    
    public Repository(DbContext context)
    {
        _context = context;
        _dbSet = context.Set<T>();
    }
    
    public virtual async Task<T> GetByIdAsync(int id)
    {
        return await _dbSet.FindAsync(id);
    }
    
    public virtual async Task<IEnumerable<T>> GetAllAsync()
    {
        return await _dbSet.ToListAsync();
    }
    
    public virtual async Task AddAsync(T entity)
    {
        await _dbSet.AddAsync(entity);
        await _context.SaveChangesAsync();
    }
    
    public virtual async Task UpdateAsync(T entity)
    {
        _dbSet.Update(entity);
        await _context.SaveChangesAsync();
    }
    
    public virtual async Task DeleteAsync(int id)
    {
        var entity = await GetByIdAsync(id);
        if (entity != null)
        {
            _dbSet.Remove(entity);
            await _context.SaveChangesAsync();
        }
    }
}

Middleware Pipeline in ASP.NET Core

Understanding the middleware pipeline is essential for ASP.NET Core development:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // Exception handling middleware (early in pipeline)
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
    }
    
    // HTTPS redirection
    app.UseHttpsRedirection();
    
    // Static files
    app.UseStaticFiles();
    
    // Routing
    app.UseRouting();
    
    // Authentication
    app.UseAuthentication();
    app.UseAuthorization();
    
    // Custom middleware
    app.Use(async (context, next) =>
    {
        // Pre-processing
        var startTime = DateTime.UtcNow;
        
        await next(); // Call next middleware
        
        // Post-processing
        var duration = DateTime.UtcNow - startTime;
        context.Response.Headers.Add("X-Response-Time", duration.TotalMilliseconds.ToString());
    });
    
    // Endpoints
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

Common Interview Questions and Answers

Question 1: What is the difference between String and StringBuilder?

Answer: String is immutable—each operation creates a new string object, which can be inefficient for multiple concatenations. StringBuilder is mutable and uses an internal buffer, making it more efficient for string manipulation operations.

// Inefficient - creates multiple string objects
string result = "";
for (int i = 0; i < 1000; i++)
{
    result += i.ToString(); // Creates new string each time
}

// Efficient - uses internal buffer
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++)
{
    sb.Append(i.ToString());
}
string result = sb.ToString();

Question 2: Explain the difference between IQueryable and IEnumerable

Answer: IEnumerable executes queries in memory (client-side), while IQueryable builds expression trees that are translated to SQL and executed on the database server. Use IQueryable for database queries to leverage server-side filtering and reduce data transfer.

Question 3: What are Extension Methods?

Answer: Extension methods allow you to add methods to existing types without modifying their source code. They must be static methods in a static class and use the this keyword for the first parameter.

public static class StringExtensions
{
    public static bool IsValidEmail(this string email)
    {
        return !string.IsNullOrEmpty(email) && 
               email.Contains("@") && 
               email.Contains(".");
    }
}

// Usage
string email = "user@example.com";
bool isValid = email.IsValidEmail();

Behavioral Interview Tips for .NET Roles

Demonstrating Problem-Solving Skills

Questions to Ask the Interviewer

Mock Interview Practice Questions

Technical Scenario 1: Design a Caching Strategy

Question: "How would you implement a distributed caching solution for a high-traffic web application?"

Approach: Discuss using Redis or Azure Cache for Redis, implementing cache-aside pattern, setting appropriate TTL values, handling cache invalidation, and considering cache warming strategies for critical data.

Technical Scenario 2: Optimize Database Queries

Question: "A web application is experiencing slow page loads. How would you diagnose and fix the performance issues?"

Approach: Mention using Application Insights or profiling tools, analyzing slow queries, implementing proper indexing, using async/await for I/O operations, considering pagination, and implementing query result caching where appropriate.

Conclusion

Mastering .NET interview questions requires a combination of theoretical knowledge and practical experience. Focus on understanding core concepts deeply, practicing coding challenges, and being able to explain your thought process. Remember that interviewers value candidates who can not only write code but also understand the "why" behind design decisions and can communicate technical concepts clearly.

Continue practicing with real-world scenarios, contribute to open-source .NET projects, and stay updated with the latest .NET features and best practices. Good luck with your interview preparation!