Chapter 3 — Advanced C# (60 Questions)

Topics:

Async & Multithreading

  1. How async/await works internally
  2. Synchronization context
  3. ConfigureAwait
  4. Deadlocks
  5. Thread safety
  6. Locks
  7. Monitor
  8. Mutex
  9. SemaphoreSlim
  10. Concurrent collections

Advanced Language Features

  1. Expression trees
  2. Reflection deep dive
  3. Attributes
  4. Dynamic keyword
  5. Span<T>
  6. Memory<T>
  7. Unsafe code
  8. Stackalloc
  9. Yield return
  10. Iterators

Performance

  1. Boxing optimization
  2. Allocation reduction
  3. Object pooling
  4. Caching strategies
  5. Profiling

Advanced LINQ

  1. Expression vs Func
  2. SelectMany
  3. GroupBy
  4. Join
  5. Aggregate

Enterprise C#

31–60:

. How does async/await work internally in C#?

Interview Answer

async and await are compiler features that simplify asynchronous programming. The compiler transforms an async method into a state machine.

Example:

public async Task<string> GetDataAsync()

{

    var result = await httpClient.GetStringAsync(url);

    return result;

}

The compiler converts this into a state machine that:

  1. Starts executing the method.
  2. Runs until it reaches await.
  3. Checks whether the task is completed.
  4. If not completed, returns control to the caller.
  5. Continues execution when the task completes.

Important Point

await does not block the thread.

While waiting for an HTTP request or database call:

This improves application scalability.


Follow-up Question

Q: Does async/await create a new thread?

Answer

No.

For I/O operations:

await database.GetDataAsync();

No new thread is usually created.

The operating system handles the I/O operation, and the application continues when the operation completes.


2. What is the difference between synchronous and asynchronous programming?

Interview Answer

Synchronous programming

Operations execute one after another.

Example:

var data = GetData();

Process(data);

The second operation waits until the first finishes.


Asynchronous programming

A long-running operation can continue without blocking execution.

Example:

var data = await GetDataAsync();

Process(data);


Comparison

Synchronous

Asynchronous

Blocks execution

Does not block while waiting

Simpler

More scalable

Good for CPU operations

Good for I/O operations

Uses fewer concepts

Requires async flow


Senior Answer

In server applications, asynchronous programming is especially valuable because it allows handling more concurrent requests with fewer threads.


3. What is ConfigureAwait(false)?

Interview Answer

ConfigureAwait(false) tells the runtime not to capture the current synchronization context after awaiting.

Example:

await service.GetDataAsync()

              .ConfigureAwait(false);


Why does this matter?

In UI applications:

the continuation often needs to return to the UI thread.

Example:

await LoadDataAsync();

// update UI

textBox.Text = result;

The context is needed.


In server applications:

there is usually no synchronization context.

Using:

ConfigureAwait(false)

can avoid unnecessary context switching.


Senior Interview Answer

In library code, I often use ConfigureAwait(false) because the library should not depend on a caller's synchronization context.


4. What is a deadlock in asynchronous programming?

Interview Answer

A deadlock occurs when two operations wait for each other indefinitely.

A common async deadlock happens when blocking on an async method.

Example:

var result = GetDataAsync().Result;

or:

GetDataAsync().Wait();


Why is this dangerous?

The async method may need to resume on the captured context, but the thread is blocked waiting for the result.

The continuation cannot execute.

Result:

Thread waiting

      |

      |

Async operation waiting for thread


Best Practice

Avoid:

.Result

.Wait()

Prefer:

await GetDataAsync();


5. What is thread safety?

Interview Answer

Thread safety means that code behaves correctly when accessed by multiple threads simultaneously.

Example problem:

counter++;

This looks simple, but internally it involves:

  1. Read value
  2. Increment value
  3. Write value

Two threads can interfere.


Example Problem

Initial:

counter = 0

Thread A:

Read 0

Add 1

Thread B:

Read 0

Add 1

Result:

counter = 1

Expected:

counter = 2


Solutions


6. What is the lock keyword in C#?

Interview Answer

lock provides mutual exclusion. It ensures only one thread executes a critical section at a time.

Example:

private readonly object sync = new();

public void Increment()

{

    lock(sync)

    {

        counter++;

    }

}


How it works

Internally:

Monitor.Enter()

try

{

}

finally

{

    Monitor.Exit()

}


When to use lock?

Use when:


Avoid locking:

Example:

Bad:

lock(sync)

{

    await SaveToDatabaseAsync();

}


7. What is Monitor in C#?

Interview Answer

Monitor is the underlying synchronization mechanism used by lock.

Example:

Monitor.Enter(sync);

try

{

    counter++;

}

finally

{

    Monitor.Exit(sync);

}


Features

Monitor supports:

Example:

Monitor.Wait()

Monitor.Pulse()


Difference between lock and Monitor

lock:

Monitor:


8. What is Interlocked in C#?

Interview Answer

Interlocked provides atomic operations for simple shared variables.

Example:

Interlocked.Increment(ref counter);

Instead of:

counter++;


Common Methods

Interlocked.Increment()

Interlocked.Decrement()

Interlocked.Exchange()

Interlocked.CompareExchange()


When to use?

For simple operations:


Example

Without Interlocked:

counter++;

With Interlocked:

Interlocked.Increment(ref counter);

The operation cannot be interrupted.


9. What is SemaphoreSlim?

Interview Answer

SemaphoreSlim limits the number of threads or tasks that can access a resource simultaneously.

Example:

private SemaphoreSlim semaphore =

    new SemaphoreSlim(3);

public async Task ProcessAsync()

{

    await semaphore.WaitAsync();

    try

    {

        await DoWorkAsync();

    }

    finally

    {

        semaphore.Release();

    }

}


This allows:

Maximum 3 operations at the same time


Common Uses


Example

A service allows only 10 external API requests simultaneously.

Use:

new SemaphoreSlim(10);


10. What are concurrent collections in .NET?

Interview Answer

Concurrent collections are thread-safe collections designed for multi-threaded applications.

Namespace:

System.Collections.Concurrent


Examples

ConcurrentDictionary

Thread-safe dictionary:

var cache = new ConcurrentDictionary<int,string>();

cache.TryAdd(1,"John");


ConcurrentQueue

Thread-safe queue:

ConcurrentQueue<string> queue;


ConcurrentBag

Thread-safe unordered collection:

ConcurrentBag<int> numbers;


Why not use List<T>?

A normal collection:

List<int>

is not thread-safe.

Multiple threads modifying it can cause:


Senior Interview Answer

For multi-threaded applications, I prefer immutable objects or concurrent collections before adding manual locks because they reduce complexity and synchronization issues.

11. What are expression trees in C#?

Interview Answer

An expression tree represents code as a data structure that can be inspected, modified, and translated at runtime.

Unlike a normal delegate, an expression tree does not execute code directly. It describes the structure of the code.

Example:

Normal delegate:

Func<int, bool> condition = x => x > 10;

This creates executable code.

Expression tree:

Expression<Func<int, bool>> condition =

    x => x > 10;

This creates a representation of:

Parameter: x

Operation: GreaterThan

Value: 10


Common Uses

Expression trees are heavily used by:

Example:

var users = db.Users

    .Where(u => u.Age > 30);

Entity Framework receives the expression tree and converts it into SQL:

SELECT *

FROM Users

WHERE Age > 30


Senior Answer

Expression trees allow frameworks to analyze C# expressions and translate them into another language, such as SQL.


12. What is the difference between Func<T> and Expression<Func<T>>?

Interview Answer

The difference is execution.


Func

Represents executable code.

Example:

Func<User, bool> filter =

    u => u.Age > 18;

The code runs inside .NET.


Expression<Func>

Represents code as data.

Example:

Expression<Func<User,bool>> filter =

    u => u.Age > 18;

The framework can inspect and translate it.


Example

LINQ to Objects:

users

    .Where(u => u.Age > 18);

Uses:

Func<User,bool>


Entity Framework:

db.Users

   .Where(u => u.Age > 18);

Uses:

Expression<Func<User,bool>>


Interview Comparison

Func

Expression

Executes code

Describes code

Compiled delegate

Expression tree

LINQ-to-Objects

LINQ-to-SQL

Cannot translate

Can translate


13. What is reflection in more detail?

Interview Answer

Reflection allows examining and manipulating assemblies, types, and members during runtime.

Using reflection, you can:


Example:

Type type = typeof(Customer);

Console.WriteLine(type.Name);

Get methods:

MethodInfo[] methods =

    type.GetMethods();


Create object dynamically:

object obj =

    Activator.CreateInstance(type);


Invoke method:

method.Invoke(obj, parameters);


Real-world Examples

Dependency Injection

ASP.NET Core scans assemblies:

services.AddTransient<IService, Service>();

The container uses reflection internally.


Serialization

JSON serializers inspect:

public class Customer

{

    public string Name {get;set;}

}

and map properties.


Disadvantages

Reflection:


14. What is the dynamic keyword in C#?

Interview Answer

dynamic bypasses compile-time type checking and resolves members at runtime.

Example:

dynamic customer = GetCustomer();

Console.WriteLine(customer.Name);

The compiler does not verify that Name exists.

The check happens during execution.


Normal C#

Customer customer;

customer.Name;

The compiler checks:

"Does Customer have Name?"


Dynamic

dynamic customer;

customer.Name;

The runtime checks.


Common Uses


Disadvantages

You lose:

Example:

dynamic value = 10;

value.SomeMethod();

Compiles but fails at runtime.


15. What is ExpandoObject?

Interview Answer

ExpandoObject allows creating objects with dynamic properties at runtime.

Example:

dynamic user = new ExpandoObject();

user.Name = "John";

user.Age = 30;

The object structure is created dynamically.


Example:

Console.WriteLine(user.Name);

Output:

John


Common Uses


Difference from normal class

Class:

public class User

{

    public string Name {get;set;}

}

Structure is known at compile time.


ExpandoObject:

dynamic user;

Structure can change.


16. What are attributes and why are they useful?

Interview Answer

Attributes add metadata to code elements.

They allow frameworks to understand additional information about classes, methods, and properties.

Example:

[Required]

public string Name {get;set;}

The attribute tells validation frameworks:

"Name cannot be empty."


Common .NET Attributes

MVC/API

[HttpGet]

[Authorize]


Validation

[Required]

[StringLength(50)]


Serialization

[JsonPropertyName("customer_name")]


How frameworks use attributes

Typical process:

  1. Framework scans assemblies.
  2. Finds attributes using reflection.
  3. Applies behavior.

17. How do you create a custom attribute?

Interview Answer

Create a class derived from Attribute.

Example:

public class AuditAttribute : Attribute

{

    public string Description {get;}

    public AuditAttribute(string description)

    {

        Description = description;

    }

}

Usage:

[Audit("Creates customer")]

public void CreateCustomer()

{

}


Reading it:

var attributes =

    method.GetCustomAttributes();


Real Example

You could create:

[Permission("Admin")]

public void DeleteUser()

{

}

and check permissions automatically.


18. What are iterators in C#?

Interview Answer

An iterator allows a method to return elements one at a time instead of creating the entire collection in memory.

The yield keyword is used.

Example:

public IEnumerable<int> GetNumbers()

{

    yield return 1;

    yield return 2;

    yield return 3;

}

Usage:

foreach(var n in GetNumbers())

{

    Console.WriteLine(n);

}


Advantage

Instead of:

return new List<int>

{

    1,2,3

};

The values are generated as needed.


Benefits


19. What is yield return?

Interview Answer

yield return creates an iterator that produces values one at a time.

Example:

public IEnumerable<string> ReadLines()

{

    foreach(var line in File.ReadLines("file.txt"))

    {

        yield return line;

    }

}


The caller controls iteration:

foreach(var line in ReadLines())

{

}


Important Point

The method does not execute completely at once.

Execution pauses at:

yield return

and resumes on the next iteration.


20. What is Span<T> in C#?

Interview Answer

Span<T> is a high-performance type that allows working with contiguous memory without allocations.

Namespace:

System;


Example:

Span<int> numbers =

    stackalloc int[5];

numbers[0] = 10;


Why Span<T> exists

Traditional approach:

int[] array = new int[1000];

creates heap allocations.

Span<T> can work with:

without copying data.


Benefits


Common Uses


Example

String parsing:

ReadOnlySpan<char> text = "Hello World";

var first =

    text.Slice(0,5);

No new string is created.


Senior Interview Summary

For advanced C# questions, remember:

Expression Trees

"They represent code as data and allow frameworks like Entity Framework to translate expressions into SQL."

Reflection

"It provides runtime inspection but should be used carefully because it reduces performance and type safety."

Dynamic

"Useful when the type is unknown at compile time, but sacrifices compiler checks."

Iterators

"yield enables lazy execution and memory-efficient processing."

Span<T>

"A high-performance memory view that avoids unnecessary allocations."

21. What is the difference between Span<T> and Memory<T>?

Interview Answer

Both Span<T> and Memory<T> provide high-performance access to memory without unnecessary allocations, but they have different lifetime capabilities.


Span<T>

Span<T> is a stack-only type.

It cannot:

Example:

public void Process()

{

    Span<int> numbers = stackalloc int[10];

    numbers[0] = 100;

}


Memory<T>

Memory<T> is designed for scenarios where memory needs to survive beyond the current method.

Example:

public class DataProcessor

{

    private Memory<byte> buffer;

}

It can be:


Comparison

Span<T>

Memory<T>

Stack-only

Heap-friendly

Synchronous scenarios

Async scenarios

Faster

Slightly more overhead

Cannot cross await

Works with await


Senior Answer

I use Span<T> for high-performance synchronous processing and Memory<T> when the memory needs to live across asynchronous operations.


22. What is stackalloc in C#?

Interview Answer

stackalloc allocates memory on the stack instead of the managed heap.

Example:

Span<int> numbers = stackalloc int[100];


Normal allocation:

int[] numbers = new int[100];

Memory location:

Managed Heap


stackalloc:

Thread Stack


Advantages


Disadvantages

Stack memory is limited.

Bad:

Span<byte> buffer =

    stackalloc byte[100000000];

This can cause stack overflow.


Common Usage

High-performance code:


23. What is unsafe code in C#?

Interview Answer

Unsafe code allows direct memory manipulation using pointers.

Example:

unsafe

{

    int number = 10;

    int* pointer = &number;

    Console.WriteLine(*pointer);

}


Why use unsafe code?

Used for:


Requirements

Project must enable:

<AllowUnsafeBlocks>true</AllowUnsafeBlocks>


Should you use unsafe code?

Usually no.

Modern .NET provides safer alternatives:


Senior Answer

I avoid unsafe code unless profiling proves that managed code cannot meet performance requirements.


24. What is boxing and unboxing in C#?

Interview Answer

Boxing converts a value type into an object reference.

Unboxing extracts the value type from the object.


Boxing example:

int number = 10;

object obj = number;

The integer is copied to the heap.

int

 |

 |

object


Unboxing:

int value = (int)obj;


Performance Issue

Boxing causes:


Example

Avoid:

ArrayList list = new();

list.Add(100);

Because every integer is boxed.

Prefer:

List<int> list = new();

list.Add(100);

No boxing.


25. How do you optimize boxing/unboxing?

Interview Answer

Use generics instead of non-generic collections.

Bad:

ArrayList values = new();

values.Add(10);

Good:

List<int> values = new();

values.Add(10);


Use strongly typed APIs:

Bad:

object Process(object value)

{

}

Better:

T Process<T>(T value)

{

}


Senior Answer

Boxing is often hidden in code, so I use profiling tools to identify allocations before optimizing.


26. What is object pooling?

Interview Answer

Object pooling is a technique where objects are reused instead of constantly created and destroyed.

Instead of:

Create object

Use object

Destroy object

Create object again

Use:

Get object from pool

Use object

Return object to pool


Example

ASP.NET Core provides:

Microsoft.Extensions.ObjectPool

Example:

var pool =

    new DefaultObjectPool<MyObject>(

        new MyObjectPolicy());


Benefits


Common Uses


27. What are caching strategies in .NET?

Interview Answer

Caching stores frequently used data to avoid expensive operations.

Common strategies:


1. In-memory cache

Data stored inside application memory.

Example:

IMemoryCache cache;

Good for:


2. Distributed cache

Data stored outside application.

Examples:

Good for:


3. Cache-aside pattern

Most common approach.

Flow:

Request

 |

Check Cache

 |

Found?

 |

Return Data

Not Found

 |

Load Database

 |

Store Cache

 |

Return Data


Senior Answer

I choose cache strategy based on consistency requirements, expiration policy, and whether the application is distributed.


28. What are immutable collections in .NET?

Interview Answer

Immutable collections cannot be modified after creation.

Namespace:

System.Collections.Immutable

Examples:

ImmutableList<int> numbers =

    ImmutableList.Create(1,2,3);


Adding an item:

var updated =

    numbers.Add(4);

The original collection remains unchanged.


Benefits


Examples


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

Interview Answer

The main difference is that classes are reference types and structs are value types.


Class

Stored as reference:

class Customer

{

    public string Name;

}

Example:

Customer c1 = new();

Customer c2 = c1;

Both reference the same object.


Struct

Stored as value:

struct Point

{

    public int X;

    public int Y;

}

Example:

Point p1 = new();

Point p2 = p1;

A copy is created.


Comparison

Class

Struct

Reference type

Value type

Heap allocation

Usually stack/inline

Supports inheritance

No class inheritance

Larger objects

Small data objects


When to use struct?

Good for:

Examples:

DateTime

Guid

decimal


30. What are record types in C# and how are they different from classes?

Interview Answer

Records are reference types designed mainly for immutable data models and value-based equality.

Example:

public record Customer(

    string Name,

    int Age);


Class comparison

Class:

var c1 = new Customer("John",30);

var c2 = new Customer("John",30);

c1 == c2;

Usually:

False

because references differ.


Record:

var r1 = new Customer("John",30);

var r2 = new Customer("John",30);

r1 == r2;

Result:

True

because values are compared.


Records provide:

Example:

var updated =

    customer with { Age = 31 };


When to use records?

Good for:

Avoid for:


Senior Interview Summary

Important concepts:

Span<T>

"A high-performance memory view that avoids allocations."

Boxing

"Converting value types to objects creates allocations and should be minimized."

Object Pooling

"Reuse expensive objects to reduce GC pressure."

Struct

"Use for small value types where copying is cheaper than heap allocation."

Records

"Use for immutable data transfer models with value-based equality."

31. What is the difference between Select and SelectMany in LINQ?

Interview Answer

Both are projection operators, but they work differently.


Select

Select transforms each element into another form.

Example:

var names = customers

    .Select(c => c.Name);

Input:

Customer[]

   |

   |

string[]

Example:

var numbers = new[] {1,2,3};

var result = numbers.Select(x => x * 2);

Result:

2,4,6


SelectMany

SelectMany flattens nested collections into a single collection.

Example:

class Customer

{

    public string Name {get;set;}

    public List<Order> Orders {get;set;}

}

Without SelectMany:

var orders =

    customers.Select(c => c.Orders);

Result:

List<Order>

List<Order>

List<Order>

Nested collections.


With SelectMany:

var orders =

    customers.SelectMany(c => c.Orders);

Result:

Order

Order

Order

Order


Senior Answer

I use Select for one-to-one transformations and SelectMany when I need to flatten nested collections.


32. How does GroupBy work in LINQ?

Interview Answer

GroupBy groups elements based on a key.

Example:

var employeesByDepartment =

    employees.GroupBy(e => e.Department);

Result:

IT

 ├── John

 ├── Mary

HR

 ├── Alex

 ├── Peter


Example:

foreach(var group in employeesByDepartment)

{

    Console.WriteLine(group.Key);

    foreach(var employee in group)

    {

        Console.WriteLine(employee.Name);

    }

}


SQL Equivalent

LINQ:

employees.GroupBy(e => e.Department)

SQL:

SELECT Department, COUNT(*)

FROM Employees

GROUP BY Department


Performance Consideration

GroupBy usually loads data into memory.

For large database tables:

Prefer:

IQueryable

so the grouping can happen in SQL.


33. What are Join operations in LINQ?

Interview Answer

LINQ joins combine data from two collections based on a matching key.

Example:

var result =

    customers.Join(

        orders,

        c => c.Id,

        o => o.CustomerId,

        (customer, order) =>

        new

        {

            customer.Name,

            order.Amount

        });


Equivalent SQL:

SELECT

    Customers.Name,

    Orders.Amount

FROM Customers

JOIN Orders

ON Customers.Id = Orders.CustomerId


Types of LINQ joins

Inner Join

Returns matching records only.

Example:

Customers

    +

Orders

Only customers with orders.


Left Join

Returns all records from the left side.

Example:

All customers, even without orders.


LINQ uses:

DefaultIfEmpty()

for left joins.


34. What is Aggregate in LINQ?

Interview Answer

Aggregate applies a function repeatedly to combine values into a single result.

Example:

var numbers = new[] {1,2,3,4};

var sum =

    numbers.Aggregate(

        0,

        (total, number) => total + number);

Result:

10


Execution:

0 + 1 = 1

1 + 2 = 3

3 + 3 = 6

6 + 4 = 10


Common Uses

Example:

var sentence =

    words.Aggregate(

        "",

        (a,b) => a + " " + b);


Difference from Sum()

Instead of:

numbers.Sum();

Use Aggregate when the operation is custom.


35. What is deferred execution in LINQ?

Interview Answer

Deferred execution means a LINQ query is not executed when it is created.

It executes when the results are requested.

Example:

var query =

    customers.Where(c => c.Active);

Nothing has happened yet.

Execution occurs:

var list = query.ToList();


Benefits


Example:

var query =

    customers

    .Where(c => c.Active)

    .OrderBy(c => c.Name);

The entire query executes only at:

.ToList()


36. What is immediate execution in LINQ?

Interview Answer

Immediate execution happens when a LINQ method forces the query to run immediately.

Examples:

.ToList()

.ToArray()

.Count()

.First()

.Single()


Example:

var users =

    db.Users

      .Where(u => u.Active)

      .ToList();

The SQL executes immediately.


Important Interview Point

Calling:

Count()

executes the query.

Calling:

Where()

does not.


37. What is the difference between IEnumerable and IQueryable internally?

Interview Answer

The main difference is how LINQ expressions are executed.


IEnumerable

Works with:

Objects in memory

Example:

List<Customer> customers;

customers

    .Where(c => c.Active);

Execution:

Database

   |

Load all data

   |

Memory filtering


IQueryable

Builds an expression tree.

Example:

db.Customers

  .Where(c => c.Active);

Execution:

LINQ Expression

       |

Entity Framework

       |

SQL

       |

Database


Senior Answer

IQueryable allows the query provider to translate expressions into another language, such as SQL, while IEnumerable executes using CLR objects.


38. What are LINQ expression trees used for?

Interview Answer

Expression trees allow LINQ providers to analyze queries.

Example:

Expression<Func<Customer,bool>>

represents:

customer => customer.Active

as a structure:

Lambda Expression

 |

 +-- Parameter: customer

 |

 +-- Property: Active

 |

 +-- Operator: Equal


Entity Framework converts it:

C#:

.Where(c => c.Active)

SQL:

WHERE Active = 1


39. How can you improve LINQ performance?

Interview Answer

Several techniques improve LINQ performance:


1. Avoid unnecessary ToList()

Bad:

var list =

    customers

    .Where(c=>c.Active)

    .ToList()

    .OrderBy(c=>c.Name);

The query executes too early.

Better:

var result =

    customers

    .Where(c=>c.Active)

    .OrderBy(c=>c.Name)

    .ToList();


2. Select only required fields

Bad:

var users =

    db.Users.ToList();

Loads everything.

Better:

var users =

    db.Users

      .Select(x => new

      {

          x.Id,

          x.Name

      });


3. Avoid multiple enumeration

Bad:

var count = query.Count();

var first = query.First();

The query executes twice.

Better:

var list = query.ToList();

var count = list.Count;

var first = list.First();


40. What are common LINQ mistakes?

Interview Answer


Mistake 1: Executing queries too early

Bad:

var users =

    db.Users

      .ToList()

      .Where(u => u.Active);

The database returns all users first.

Better:

var users =

    db.Users

      .Where(u => u.Active)

      .ToList();


Mistake 2: Loading unnecessary data

Bad:

var customers =

    db.Customers.ToList();

Better:

var customers =

    db.Customers

      .Select(c => c.Name)

      .ToList();


Mistake 3: N+1 queries

Example:

foreach(var customer in customers)

{

    customer.Orders.Count();

}

May generate many database calls.

Better:

Use:


Senior Interview Summary

Important LINQ concepts:

Select

"Transforms each item."

SelectMany

"Flattens nested collections."

IQueryable

"Allows query translation, usually into SQL."

Deferred Execution

"Queries execute only when results are requested."

Performance

"Filter and project data at the database level whenever possible."

41. How does Dependency Injection work internally in ASP.NET Core?

Interview Answer

Dependency Injection (DI) is a design pattern where objects receive their dependencies from an external container instead of creating them directly.

Without DI:

public class OrderService

{

    private readonly EmailService emailService;

    public OrderService()

    {

        emailService = new EmailService();

    }

}

Problems:


With DI:

public class OrderService

{

    private readonly IEmailService emailService;

    public OrderService(

        IEmailService emailService)

    {

        this.emailService = emailService;

    }

}

Registration:

services.AddScoped<IEmailService, EmailService>();

The framework creates and injects the dependency.


Internally

ASP.NET Core uses:

Service Collection

        |

        |

Service Provider

        |

        |

Object Creation

        |

        |

Constructor Injection

The container:

  1. Finds the requested service.
  2. Determines its dependencies.
  3. Creates required objects.
  4. Controls their lifetime.

Senior Answer

Dependency Injection reduces coupling and improves testability. ASP.NET Core has a built-in DI container that manages object creation and lifetimes.


42. What is IServiceCollection and IServiceProvider?

Interview Answer

They are the two main parts of ASP.NET Core Dependency Injection.


IServiceCollection

Used during application startup to register services.

Example:

builder.Services.AddScoped<IUserService, UserService>();

It stores service registrations.


IServiceProvider

Used at runtime to resolve services.

Example:

var service =

    provider.GetService<IUserService>();

It creates objects based on registrations.


Flow

IServiceCollection

(Register services)

        ↓

IServiceProvider

(Create objects)

        ↓

Application


43. What are the DI service lifetimes in ASP.NET Core?

Interview Answer

ASP.NET Core provides three lifetimes.


Transient

A new instance every time requested.

services.AddTransient<IEmailService, EmailService>();

Example:

Request A

 |

EmailService #1

Request A

 |

EmailService #2

Good for:


Scoped

One instance per request.

services.AddScoped<IOrderService, OrderService>();

Example:

HTTP Request

 |

OrderService

 |

Database Context

Common for:


Singleton

One instance for application lifetime.

services.AddSingleton<ICache, Cache>();

Good for:


Interview Tip

Remember:

Transient = Every time

Scoped = Every request

Singleton = Application lifetime


44. What is middleware in ASP.NET Core?

Interview Answer

Middleware is a component that handles HTTP requests and responses in the ASP.NET Core pipeline.

Example:

app.UseAuthentication();

app.UseAuthorization();

app.MapControllers();


Pipeline Example

HTTP Request

     |

     v

Logging Middleware

     |

     v

Authentication Middleware

     |

     v

Authorization Middleware

     |

     v

Controller

     |

     v

HTTP Response


Custom Middleware Example

public class LoggingMiddleware

{

    private readonly RequestDelegate next;

    public LoggingMiddleware(

        RequestDelegate next)

    {

        this.next = next;

    }

    public async Task Invoke(HttpContext context)

    {

        Console.WriteLine(

            context.Request.Path);

        await next(context);

    }

}


Registration:

app.UseMiddleware<LoggingMiddleware>();


45. What is the difference between middleware and filters?

Interview Answer

Both can intercept requests, but they work at different levels.


Middleware

Works at HTTP pipeline level.

Examples:

Runs before MVC.


Filters

Work inside MVC pipeline.

Examples:

Example:

public class AuditFilter : IActionFilter

{

}


Comparison

Middleware

Filter

HTTP pipeline

MVC pipeline

Applies globally

Controller/action level

Framework independent

MVC specific


Senior Answer

I use middleware for cross-cutting concerns that apply to the whole application and filters when behavior is specific to MVC actions.


46. What are Background Services in ASP.NET Core?

Interview Answer

Background services allow running long-running tasks outside the normal HTTP request pipeline.

They are implemented using:

BackgroundService

Example:

public class EmailWorker

    : BackgroundService

{

    protected override async Task ExecuteAsync(

        CancellationToken stoppingToken)

    {

        while(!stoppingToken.IsCancellationRequested)

        {

            await SendEmails();

            await Task.Delay(

                5000,

                stoppingToken);

        }

    }

}


Registration:

services.AddHostedService<EmailWorker>();


Common Uses


47. What is the difference between IHostedService and BackgroundService?

Interview Answer

BackgroundService is an abstract implementation of IHostedService.


IHostedService

You implement:

StartAsync()

StopAsync()

Example:

public class Worker : IHostedService

{

}


BackgroundService

Provides a simpler model:

protected abstract Task ExecuteAsync();

Example:

public class Worker

    : BackgroundService

{

}


Senior Answer

I usually use BackgroundService because it provides a cleaner implementation for continuous background processing.


48. How does configuration work in ASP.NET Core?

Interview Answer

ASP.NET Core uses a configuration system that combines values from multiple sources.

Common sources:


Example:

appsettings.json:

{

  "Database": {

    "ConnectionString": "Server=myserver"

  }

}

Read:

var value =

    configuration["Database:ConnectionString"];


Priority

Later providers override earlier ones.

Example:

appsettings.json

        ↓

Environment Variables

        ↓

Command Line


49. How does logging work in ASP.NET Core?

Interview Answer

ASP.NET Core provides built-in logging through:

ILogger<T>

Example:

public class OrderService

{

    private readonly ILogger<OrderService> logger;

    public OrderService(

        ILogger<OrderService> logger)

    {

        this.logger = logger;

    }

    public void Process()

    {

        logger.LogInformation(

            "Order processed");

    }

}


Log Levels

From lowest to highest:

Trace

Debug

Information

Warning

Error

Critical


Logging Providers

Examples:


Senior Answer

I use structured logging instead of plain text because it allows better searching and analysis in production environments.

Example:

logger.LogInformation(

    "Order {OrderId} created",

    orderId);


50. What are Health Checks in ASP.NET Core?

Interview Answer

Health checks provide endpoints that report whether an application and its dependencies are healthy.

Example:

Registration:

services.AddHealthChecks();

Endpoint:

app.MapHealthChecks("/health");


A monitoring system can call:

GET /health

Response:

{

  "status":"Healthy"

}


What can health checks test?

Examples:


Example:

services

.AddHealthChecks()

.AddSqlServer(connectionString);


Common Usage

Used by:


Senior Interview Summary

Important ASP.NET Core concepts:

Dependency Injection

"The container manages object creation and lifetime."

Middleware

"Middleware forms the HTTP request processing pipeline."

BackgroundService

"Used for long-running tasks outside HTTP requests."

Configuration

"Multiple providers are combined with later providers overriding earlier values."

Logging

"Use structured logging for production diagnostics."

Health Checks

"Used by infrastructure to determine application availability."

51. What are Minimal APIs in ASP.NET Core?

Interview Answer

Minimal APIs provide a lightweight way to build HTTP APIs without the traditional Controller-based approach.

Introduced in .NET 6, they reduce boilerplate code.


Traditional Controller:

[ApiController]

[Route("api/users")]

public class UsersController : ControllerBase

{

    [HttpGet]

    public IEnumerable<User> Get()

    {

        return users;

    }

}


Minimal API:

var builder = WebApplication.CreateBuilder(args);

var app = builder.Build();

app.MapGet("/users", () =>

{

    return users;

});

app.Run();


Advantages


When to use?

Good for:

Use Controllers for:


Senior Answer

Minimal APIs are useful when simplicity and performance are priorities, while Controllers provide better structure for large enterprise applications.


52. What is endpoint routing in ASP.NET Core?

Interview Answer

Endpoint routing maps incoming HTTP requests to application endpoints.

Example:

app.MapGet("/customers/{id}",

    (int id) =>

    {

        return GetCustomer(id);

    });

Request:

GET /customers/10

is mapped to:

Handler(id = 10)


Routing Pipeline

HTTP Request

      |

      v

Routing Middleware

      |

      v

Endpoint Selection

      |

      v

Controller / Minimal API

      |

      v

Response


Benefits


53. What is the difference between authentication and authorization?

Interview Answer

Authentication answers:

"Who are you?"

Authorization answers:

"What are you allowed to do?"


Authentication Example

User logs in:

Username + Password

        |

Identity verified

        |

JWT Token created


Authorization Example

User has:

Role = Manager

Can access:

/reports

but not:

/admin/settings


ASP.NET Core Example

Authentication:

app.UseAuthentication();

Authorization:

app.UseAuthorization();


Senior Answer

Authentication establishes identity, while authorization determines permissions based on roles, claims, or policies.


54. What are claims in ASP.NET Core?

Interview Answer

Claims are pieces of information about a user.

Examples:

UserId = 123

Email = john@test.com

Role = Admin

Department = Finance


JWT example:

{

 "sub":"123",

 "name":"John",

 "role":"Admin"

}


Access claims:

var userId =

    User.FindFirst("sub")?.Value;


Why use claims?

Claims support:


55. What are authorization policies in ASP.NET Core?

Interview Answer

Policies provide flexible authorization rules beyond simple roles.


Example:

Create policy:

builder.Services

.AddAuthorization(options =>

{

    options.AddPolicy(

        "SeniorEmployee",

        policy =>

        {

            policy.RequireClaim(

                "Level",

                "Senior");

        });

});


Use:

[Authorize(

 Policy="SeniorEmployee")]

public IActionResult Reports()

{

    return View();

}


Advantages

Policies allow rules based on:


Senior Answer

Policies are preferable to hardcoded role checks because they separate authorization rules from application code.


56. How do JWT tokens work?

Interview Answer

JWT (JSON Web Token) is a compact token used for authentication between clients and servers.

A JWT contains three parts:

Header.Payload.Signature

Example:

xxxxx.yyyyy.zzzzz


Authentication Flow

Client

 |

 | username/password

 v

Authentication Server

 |

 | JWT Token

 v

Client

 |

 | Authorization: Bearer token

 v

API


JWT Structure

Header:

{

 "alg":"HS256"

}

Payload:

{

 "userId":123,

 "role":"Admin"

}

Signature:

Used to verify the token was not modified.


Advantages


Disadvantages


57. How do you implement global exception handling in ASP.NET Core?

Interview Answer

Global exception handling centralizes error processing.

Instead of:

try

{

}

catch(Exception ex)

{

}

everywhere, use middleware.


Example:

app.UseExceptionHandler("/error");


Custom middleware:

public class ExceptionMiddleware

{

    private readonly RequestDelegate next;

    public async Task Invoke(HttpContext context)

    {

        try

        {

            await next(context);

        }

        catch(Exception ex)

        {

            context.Response.StatusCode = 500;

        }

    }

}


Benefits


Example response:

{

 "message":"An unexpected error occurred"

}


58. What is the Result Pattern?

Interview Answer

The Result Pattern represents success or failure without using exceptions for normal business flow.


Instead of:

throw new Exception(

"Insufficient balance");

Use:

return Result.Fail(

"Insufficient balance");


Example:

public class Result<T>

{

    public bool Success {get;}

    public string Error {get;}

    public T Value {get;}

}


Usage:

var result =

    service.CreateOrder();

if(!result.Success)

{

    return BadRequest(result.Error);

}


Benefits


Common Use

Used in:


59. What is Fluent API in Entity Framework Core?

Interview Answer

Fluent API configures database mappings using C# code instead of attributes.

Example:

protected override void OnModelCreating(

    ModelBuilder builder)

{

    builder.Entity<Customer>()

        .HasKey(x => x.Id);

}


Configure relationships:

Example:

builder.Entity<Order>()

    .HasOne(o => o.Customer)

    .WithMany(c => c.Orders)

    .HasForeignKey(o => o.CustomerId);


Fluent API vs Data Annotations

Fluent API

Attributes

More powerful

Simpler

Central configuration

Mixed with model

Better for complex mappings

Good for simple cases


Senior Answer

For enterprise systems I usually prefer Fluent API because it keeps domain models clean.


60. What are EF Core performance optimization techniques?

Interview Answer

Important EF Core optimization techniques:


1. Select only required columns

Bad:

var users =

    db.Users.ToList();

Loads everything.

Better:

var users =

    db.Users

      .Select(x => new

      {

          x.Id,

          x.Name

      })

      .ToList();


2. Use AsNoTracking for read-only queries

Default:

db.Users.ToList();

EF tracks changes.

For reports:

db.Users

  .AsNoTracking()

  .ToList();

Less memory usage.


3. Avoid N+1 queries

Bad:

foreach(var customer in customers)

{

    customer.Orders.Count();

}

Can create many SQL calls.

Better:

db.Customers

.Include(c => c.Orders);


4. Use pagination

Bad:

db.Products.ToList();

Better:

db.Products

.Skip(100)

.Take(50);


5. Use indexes

Example:

CREATE INDEX IX_User_Email

ON Users(Email)


Senior Answer

EF Core performance depends on controlling generated SQL, minimizing data transfer, using proper indexes, and avoiding unnecessary tracking.


Chapter 3 — Advanced C# Completed ✅

Total Questions Completed: 60

You should now be comfortable answering:

✅ Async/await
✅ Multithreading
✅ Locks and synchronization
✅ Reflection
✅ Expression trees
✅ LINQ internals
✅ Memory optimization
✅ Dependency Injection
✅ Middleware
✅ Authentication
✅ JWT
✅ EF Core optimization