Beginner Level (0–1 Years)

1. What is the default access modifier for a class in C#?

Answer:

The default access modifier for a top-level class in C# is internal, meaning it is accessible only within the same assembly.

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

Answer:

const values are set at compile time and cannot change. readonly fields can be assigned at runtime in a constructor and remain constant afterward.

3. Can a struct inherit from another struct in C#?

Answer:

No, structs cannot inherit from another struct or class, except implicitly from System.ValueType. They can implement interfaces.

4. What is the output when a variable is assigned with a post-increment operator in C#?

Answer:

The output is 5. For example, in the code:

int a = 5;
int b = a++;
Console.WriteLine(b);

The post-increment a++ assigns 5 to b before incrementing a to 6.

5. What is the difference between Equals() and == in C#?

Answer:

Equals() is an instance method that checks for value equality and can be overridden. == is a static operator that checks for reference equality by default but can be overloaded.

6. Can you override a static method in C#?

Answer:

No, static methods cannot be overridden because they belong to the type, not an instance.

7. What is the output when using the null-conditional operator on a null string in C#?

Answer:

The output is nothing (no output). For example, in the code:

string s = null;
Console.WriteLine(s?.Length);

The null-conditional operator ?. prevents accessing Length on null, and Console.WriteLine(null) produces no output.

8. Is List<T> thread-safe in C#?

Answer:

No, List<T> is not thread-safe for concurrent read/write operations. Use locking or System.Collections.Concurrent collections for thread safety.

9. What is boxing and unboxing in C#?

Answer:

Boxing converts a value type to object, allocating memory on the heap. Unboxing extracts the value type from the object. Boxing can impact performance.

10. Can you use async without await?

Answer:

Yes, but it generates a compiler warning. The method runs synchronously, returning a Task, which can be misleading and cause issues.

11. How is a Dictionary different from a Hashtable?

Answer:

Dictionary<TKey, TValue> is generic and type-safe, while Hashtable uses object types, requiring casting. Dictionary is faster due to compile-time type checks.

12. What is the default value of a boolean in a class?

Answer:

The default value of a bool field in a class is false.

13. Can a finally block override a return statement in try or catch?

Answer:

Yes, a return in a finally block overrides returns in try or catch. This is bad practice as it can obscure control flow.

14. What does the using statement do?

Answer:

The using statement ensures IDisposable.Dispose() is called automatically, even if an exception occurs, preventing resource leaks.

15. Does throw ex; preserve the original stack trace?

Answer:

No, throw ex; resets the stack trace. Use throw; to preserve the original exception’s stack trace.

16. What’s the difference between abstract and virtual methods?

Answer:

abstract methods have no implementation and must be overridden. virtual methods have a default implementation and can be optionally overridden.

17. What is a nullable type in C#, and how do you declare it?

Answer:

A nullable type can hold its underlying type’s values plus null. It’s declared with ?, e.g., int?.

18. What does the default keyword return for a string type in C#?

Answer:

It returns null, as the default value of a reference type is null. For example, default(string) evaluates to null.

19. What is the difference between Task and Thread?

Answer:

Task is a high-level abstraction in the Task Parallel Library, more lightweight and easier to manage. Thread is lower-level, heavier, and harder to control.

20. Can a constructor be private in C#?

Answer:

Yes, private constructors are used in singleton patterns or static classes to prevent instantiation.

21. Can an interface contain fields?

Answer:

No, interfaces cannot contain fields. They can define properties, methods, events, and indexers.

22. What is the significance of async Task vs async void?

Answer:

async Task supports awaiting and proper exception handling. async void is fire-and-forget, used only for event handlers, as it cannot be awaited and exceptions are harder to catch.

23. What is Dependency Injection in .NET, and why is it used?

Answer:

Dependency Injection is a design pattern where dependencies are provided to a class instead of being created inside it. In .NET, it’s used to improve modularity, testability, and maintainability, often via the built-in DI container in ASP.NET Core.

24. What is LINQ in C#, and what is an example of a simple LINQ query?

Answer:

LINQ (Language Integrated Query) is a C# feature for querying data collections. Example: var numbers = { 1, 2, 4, 4 }; var evens = numbers.Where(n => n % 2 == 0); returns {2, 4}.

25. What is the purpose of multiple catch blocks in a try-catch statement?

Answer:

Multiple catch blocks allow handling specific exception types differently. They are evaluated in order, and the first matching block executes, enabling precise control over exception handling.


👋 Need top .NET developers for your project? Interview this week!

Fill out the form to book a call with our team. We’ll match you to the top developers who meet your requirements, and you’ll be interviewing this week!

Request for Service


Intermediate Level (1–3 Years)

1. What is the difference between ref and out parameters in C#?

Answer:

Both ref and out pass arguments by reference. However, ref requires the variable to be initialized before it is passed, while out does not. out parameters must be assigned a value before the method returns.

2. What is the difference between Task.Run() and Task.Factory.StartNew()?

Answer:

Task.Run() is simpler and preferred for CPU-bound operations. Task.Factory.StartNew() is more flexible but more complex and may not use the default TaskScheduler unless configured.

3. What is the difference between IEnumerable and IQueryable?

Answer:

IEnumerable executes queries in memory (client-side), while IQueryable builds an expression tree that can be translated to a data source (like SQL) and executed server-side, allowing for more efficient queries.

4. Can subscribing to an event without unsubscribing cause a memory leak in C#?

Answer:

Yes, if the event is never unsubscribed, it will keep a reference to the subscriber’s object, preventing it from being garbage collected, causing a memory leak. For example:

eventHandler += SomeMethod;

To avoid this, ensure the event is unsubscribed using eventHandler -= SomeMethod; when appropriate.

5. What is the difference between yield return and return in a method?

Answer:

yield return is used in iterator blocks and allows deferred execution of values one at a time. return exits the method immediately. yield return creates a state machine under the hood.

6. What is the purpose of ConfigureAwait(false) in asynchronous programming?

Answer:

ConfigureAwait(false) tells the task not to resume on the original synchronization context (e.g., UI thread). This improves performance and avoids deadlocks in some cases, especially in library code.

7. What is the difference between readonly and immutable?

Answer:

readonly means the field can only be assigned once (typically in the constructor). It does not make the object immutable. An object is immutable only if its state cannot change after creation.

8. What is the difference between value equality and reference equality?

Answer:

Value equality checks whether the content is the same (e.g., two strings with the same characters), while reference equality checks whether both variables point to the same object in memory.

9. What is the purpose of volatile keyword in C#?

Answer:

volatile ensures that a variable is always read from and written to the main memory, preventing caching issues in multi-threaded scenarios. It guarantees visibility but not atomicity.

10. How does a finally block behave if an exception is thrown inside it?

Answer:

If an exception is thrown in a finally block, it will override any previous exceptions from try or catch. This can hide original exceptions and complicate debugging.

11. What is middleware in ASP.NET Core, and how is it used?

Answer:

Middleware in ASP.NET Core is a component that handles requests and responses in the request pipeline. It’s used to process HTTP requests, such as authentication, logging, or routing. Middleware is configured in the Startup or Program class using app.Use or app.Map. For example:

app.Use(async (context, next) => { await context.Response.WriteAsync("Hello"); await next(); });

Each middleware can pass control to the next via next() or terminate the pipeline.

12. Why should you avoid async void methods except in event handlers?

Answer:

async void methods can’t be awaited or caught by try/catch blocks outside the method. This makes error handling difficult and should only be used for event handlers where no return is expected.

13. What does the lock keyword do in C#?

Answer:

The lock statement ensures that one thread does not enter a critical section of code while another thread is in that section. It provides mutual exclusion to avoid race conditions.

14. What is a race condition and how can you prevent it?

Answer:

A race condition occurs when multiple threads access shared data and try to change it simultaneously. You can prevent it using synchronization primitives like lock, Mutex, or Monitor.

15. What is the difference between StringBuilder and string when modifying strings?

Answer:

string is immutable, so each modification creates a new object. StringBuilder is mutable and more efficient for frequent or complex string manipulations.

16. Can you use async/await inside a lock block?

Answer:

No, await inside a lock block will not compile. This is because await may cause the method to exit and resume later, breaking the integrity of the lock.

17. How is ConcurrentDictionary different from Dictionary?

Answer:

ConcurrentDictionary is thread-safe and allows multiple threads to read and write concurrently without explicit locking. Dictionary is not thread-safe and requires external synchronization.

18. What is a deadlock and how can you avoid it?

Answer:

A deadlock occurs when two or more threads wait on each other to release resources. Avoid it by acquiring locks in a consistent order and avoiding circular dependencies.

19. What is a memory leak in .NET and how can it occur in managed code?

Answer:

Even though .NET has garbage collection, memory leaks can occur when references are unintentionally held, such as through static events or collections, preventing objects from being collected.

20. What does GC.Collect() do and why is it discouraged in production code?

Answer:

GC.Collect() forces garbage collection. It’s discouraged because the garbage collector is optimized to run at appropriate times. Forcing it may hurt performance and responsiveness.

21. What is the difference between throw and throw ex in exception handling?

Answer:

throw preserves the original stack trace, while throw ex resets it, making debugging harder by hiding the origin of the exception.

22. What is the use of the params keyword in C#?

Answer:

params allows a method to accept a variable number of arguments as a single array parameter. It must be the last parameter in the method signature.

23. What is the difference between is and as in C#?

Answer:

is checks whether an object is of a specific type and returns a boolean. as tries to cast and returns null if the cast fails, rather than throwing an exception.

24. What is the significance of sealed classes?

Answer:

A sealed class cannot be inherited. This is useful for preventing further derivation when the implementation is complete or for performance optimizations by the compiler or JIT.

25. What are extension methods and when would you use them?

Answer:

Extension methods allow you to add methods to existing types without modifying them. They are declared as static methods in static classes, with the first parameter prefixed with this.

26. What is the difference between abstract classes and interfaces?

Answer:

Abstract classes can have implementation and state (fields), while interfaces can only define method/property signatures (prior to C# 8). A class can implement multiple interfaces but only inherit from one class.

27. What is deferred execution in LINQ?

Answer:

Deferred execution means the query is not executed until the result is iterated (e.g., with foreach). This allows data to be up-to-date and efficient but can lead to surprises if the underlying data changes.

28. What are anonymous types in C#?

Answer:

Anonymous types allow you to create objects with read-only properties without defining a class. They’re often used in LINQ projections. Example: var person = new { Name = "Alice", Age = 30 };

29. How does dynamic differ from object in C#?

Answer:

dynamic bypasses compile-time type checking. Errors are detected at runtime. object requires casting and is checked at compile time, offering type safety.

30. What is method hiding and how is it different from method overriding?

Answer:

Method hiding uses the new keyword and replaces a method in a base class, but only when accessed through the derived type. Overriding uses override and replaces the base method even when accessed via base class reference.

31. What is a tuple in C# and how is it different from an anonymous type?

Answer:

Tuples are ordered, fixed-size collections of elements with or without named fields. Unlike anonymous types, tuples can be returned from methods and used across method boundaries.

32. What is the purpose of the nameof operator?

Answer:

nameof returns the name of a variable, type, or member as a string at compile time. It’s useful for refactoring-safe error messages, logging, or data binding.

33. What is the difference between GetAwaiter().GetResult() and Wait()?

Answer:

GetResult() throws the original exception, while Wait() wraps it in an AggregateException. Also, Wait() can more easily cause deadlocks in UI contexts.

34. What are the different dependency injection lifetime scopes in .NET, and when would you use each?

Answer:

In .NET, dependency injection supports three lifetime scopes: Transient (new instance per request, used for lightweight services), Scoped (same instance within a scope, e.g., HTTP request, used for database contexts), and Singleton (same instance for the application, used for shared resources like configuration). For example:

builder.Services.AddTransient<IService, Service>();
builder.Services.AddScoped<IRepository, Repository>();
builder.Services.AddSingleton<IConfig, Config>();

35. Can you use LINQ with non-generic collections like ArrayList?

Answer:

Yes, but you must cast or convert the elements. Example:

var query = arrayList.Cast().Where(s => s.Length > 3);

36. What are indexers in C#?

Answer:

Indexers allow an object to be indexed like an array. They’re defined using the this keyword with a parameter, and can be overloaded System: . They’recommonly used in collections.

37. Can you override a non-virtual method in C#?

Answer:

No, a method must be marked as virtual, abstract, or override to be overridden. Otherwise, you can only hide it using the new keyword.

38. How can you implement custom sorting in LINQ?

Answer:

You can use OrderBy() or OrderByDescending() with a lambda expression. For more complex logic, implement IComparer or use ThenBy() for secondary sort.

39. What is the difference between var and dynamic?

Answer:

var is statically typed and its type is inferred at compile time. dynamic bypasses compile-time checks and resolves operations at runtime.

40. What is the purpose of Nullable.GetValueOrDefault()?

Answer:

This method returns the value of the nullable type if it has one, or the default value for the underlying type if it is null. It prevents exceptions from being thrown due to null access.

41. What is the difference between Array and List in .NET?

Answer:

Array has a fixed size and is more performant for simple scenarios. List is a dynamic collection that grows as needed and offers more flexibility and built-in methods.

42. What happens if an exception is not caught in a try block?

Answer:

The runtime will search up the call stack for a matching catch block. If none is found, the application may crash or terminate unless a global exception handler is in place.

43. What is the difference between shallow copy and deep copy?

Answer:

A shallow copy duplicates only the top-level object and references to nested objects. A deep copy duplicates everything recursively, producing a completely independent copy.

44. Can a class implement multiple interfaces with the same method signature?

Answer:

Yes. If the method signatures are identical, one implementation can serve both. If not, explicit interface implementation is needed to disambiguate.

45. What is the default keyword used for in generics?

Answer:

default returns the default value for a type parameter. For reference types, it’s null; for value types, it’s zeroed (e.g., 0, false, etc.).

46. What is covariance and contravariance in C# generics?

Answer:

Covariance (out) allows a method to return more derived types. Contravariance (in) allows passing less derived types as parameters. They’re used in generic interfaces and delegates.

47. How does string interning work in .NET?

Answer:

.NET stores string literals in a pool. If two strings have the same value, they can reference the same object in memory. You can use String.Intern() to ensure interning.

48. How does pattern matching with the switch expression work in C#?

Answer:

The switch expression, introduced in C# 8.0, provides concise pattern matching for evaluating expressions. It returns a value based on patterns, supporting type, property, and relational patterns. For example:

int value = 42;
string result = value switch
{
    < 0 => "Negative",
    0 => "Zero",
    > 0 => "Positive",
    _ => "Unknown"
};

This evaluates to "Positive". The _ is the discard pattern for unmatched cases.

49. Can you declare a static constructor with access modifiers?

Answer:

No. Static constructors cannot have access modifiers and cannot be called directly. They are called automatically to initialize the type before the first use.

50. What is the output when comparing an object to itself using reference equality in C#?

Answer:

The output is True because the two operands are references to the same object instance, so reference equality returns true. For example:

var x = new object();
Console.WriteLine(x == x);

LATAM-Image-V2.png

Hire Top LATAM Developers: Guide

We’ve prepared this guide that covers  benefits, costs, recruitment, and remote team management to a succesful hiring of developers in LATAM. 

Fill out the form to get our guide.

Gated content


Advanced Level (3+ Years)

1. What is the purpose of the ExecutionContext in .NET?

Answer:

ExecutionContext flows ambient data across async calls and threads, such as security context, call context, and synchronization context. It’s used by the runtime to preserve logical thread identity.

2. What is the difference between ThreadStatic and AsyncLocal?

Answer:

[ThreadStatic] provides static field isolation per thread but doesn’t flow across async calls. AsyncLocal preserves data across async continuations, making it more suitable for async scenarios.

3. How does the .NET garbage collector determine whether an object is reachable?

Answer:

The GC builds a graph of object references starting from roots (e.g., static fields, thread stacks). If an object is not reachable from any root, it is considered garbage and eligible for collection.

4. What is the difference between ConcurrentQueue and BlockingCollection?

Answer:

ConcurrentQueue is a non-blocking, thread-safe FIFO collection. BlockingCollection wraps a concurrent collection and adds blocking and bounding capabilities using Take() and Add().

5. Can you deadlock yourself with async and await in a single-threaded context like a UI thread?

Answer:

Yes, blocking on .Result or .Wait() in a context requiring continuation on the same thread (e.g., UI thread) can cause a deadlock. For example:

public async Task DoWorkAsync() { await Task.Delay(1000); }
public void ButtonClick() { DoWorkAsync().Result; }

This deadlocks because .Result blocks the UI thread, preventing the continuation of DoWorkAsync from running.

6. How does Span work and why is it special?

Answer:

Span is a stack-only struct that allows safe, high-performance access to contiguous memory (arrays, slices, native memory) without allocations. It can’t be stored on the heap or captured in lambdas.

7. What is the use of MethodImpl(MethodImplOptions.AggressiveInlining)?

Answer:

It hints to the JIT compiler to inline a method aggressively. Inlining can improve performance by eliminating call overhead, though the JIT ultimately decides whether to inline.

8. What are Weak References and when should you use them?

Answer:

A WeakReference allows the GC to collect an object if no strong references exist. Useful for caching when you don’t want to prevent GC cleanup.

9. How can you inspect the IL (Intermediate Language) code of a compiled .NET assembly?

Answer:

You can use tools like ILDASM, dotPeek, ILSpy, or run ildasm.exe to decompile and analyze the Intermediate Language instructions of a compiled assembly.

10. What’s the difference between Assembly.Load and Assembly.LoadFrom?

Answer:

Assembly.Load loads from the Global Assembly Cache or by assembly name. LoadFrom loads from a specified path and can lead to binding context issues (e.g., multiple loads of the same assembly).

11. What is the difference between Assembly and Module in .NET?

Answer:

An Assembly is a compiled unit of code (DLL or EXE) with metadata and manifest. A Module is a single file within an assembly. An assembly can contain multiple modules, but usually has just one.

12. What is the difference between JIT and AOT compilation in .NET?

Answer:

JIT (Just-In-Time) compiles IL to native code at runtime. AOT (Ahead-Of-Time) compiles IL to native code at build time, reducing startup time and improving performance in some environments like iOS or .NET NativeMyType b)

13. What is the purpose of GCHandle?

Answer:

GCHandle allows you to pin objects in memory or create strong/weak handles to objects. Useful in interop scenarios where you pass references to unmanaged code.

14. How do lock statements internally work in .NET?

Answer:

lock is a syntactic sugar for Monitor.Enter and Monitor.Exit. It wraps the codeLisa code in a try/finally block to ensure the lock is released, even on exceptions.

15. What is tail call optimization and does .NET support it?

Answer:

Tail call optimization reuses the current stack frame for a method call that is the last operation in a method. .NET supports it in limited cases depending on JIT and runtime flags, more so in .NET Core.

16. How does IAsyncEnumerable differ from IEnumerable?

Answer:

IAsyncEnumerable supports asynchronous iteration using await foreach, allowing for non-blocking data streams, whereas IEnumerable is fully synchronous.

17. What is the purpose of UnmanagedCallersOnly in .NET?

Answer:

UnmanagedCallersOnly is an attribute that allows unmanaged code to call a static managed method directly without a delegate, improving interop performance. Used in native hosting scenarios.

18. What is the difference between TaskCompletionSource and ManualResetEventSlim?

Answer:

TaskCompletionSource is used for asynchronous signaling and integration with async/await. ManualResetEventSlim is a lower-level sync primitive for thread blocking and signaling.

19. Can you override an operator in C#?

Answer:

Yes, operators can be overloaded using the operator keyword in a class or struct. For example:

public static MyType operator +(MyType a, MyType b) { return new MyType(a.Value + b.Value); }

This allows custom behavior for operators like +.

20. What is the purpose of a stackalloc expression in C#?

Answer:

stackalloc allocates memory on the stack for short-lived buffers, improving performance by avoiding heap allocation. For example:

Span buffer = stackalloc byte[128];

It’s useful in performance-sensitive code but should be used cautiously to avoid stack overflow.

21. What is the difference between ref struct and struct in C#?

Answer:

ref struct types must remain on the stack and cannot be boxed, captured by lambdas, or stored in heap-based objects. Regular struct types can be boxed and stored anywhere.

22. What is a memory barrier and why is it needed in multithreading?

Answer:

A memory barrier prevents CPU or compiler reordering of read/write operations. It ensures correct execution order across threads and is used in volatile reads/writes and low-level concurrency code.

23. How do you handle thread starvation in the ThreadPool?

Answer:

Thread starvation occurs when all ThreadPool threads are busy, delaying queued work items. Mitigate it by using TaskCreationOptions.LongRunning or creating a new Thread. For example:

new Thread(() => LongRunningTask()).Start();

This ensures dedicated thread execution for long-running tasks.

24. What is the difference between Span and Memory?

Answer:

Span is stack-only and synchronous. Memory can live on the heap and be used in async methods. Memory can be sliced and converted to Span using .Span.

25. Can a finalizer resurrect an object?

Answer:

Yes, by assigning this to a static field inside the finalizer. However, this is strongly discouraged as it complicates garbage collection and can lead to memory leaks.

26. What are the differences between Dispatcher, SynchronizationContext, and TaskScheduler?

Answer:

Dispatcher is WPF-specific and used to schedule UI thread work. SynchronizationContext is a generic abstraction for synchronizing context across async calls. TaskScheduler handles task execution policy for Task instances.

27. What is the purpose of ILOffset in a stack trace?

Answer:

ILOffset indicates the offset from the start of the method where the exception occurred in IL code. It is useful for debugging and correlating with symbols or decompiled code.

28. What are the implications of using GC.KeepAlive()?

Answer:

GC.KeepAlive(obj) ensures the object is not collected before that line. It prevents premature finalization in scenarios involving native code or weak references.

29. How does .NET support function pointers (delegate*)?

Answer:

Starting in C# 9 and .NET 5, delegate* allows using unmanaged function pointers. It improves interop and performance in high-performance or native interop code, but is unsafe and requires unsafe context.

30. What is the difference between Type.GetType() and typeof()?

Answer:

typeof() is compile-time and returns a Type object for a known type. Type.GetType() is runtime and looks up a type by name; it returns null if the type cannot be found or loaded.

31. How do you prevent memory leaks when using events in .NET?

Answer:

Always unsubscribe from events when the subscriber is no longer needed. Alternatively, use WeakEventManager or weak references to prevent the event publisher from keeping the subscriber alive.

32. What is the purpose of Unsafe class in .NET?

Answer:

System.Runtime.CompilerServices.Unsafe provides low-level memory operations for performance-critical code. It bypasses safety checks and is intended for advanced scenarios like Span manipulation or interop.

33. What is the difference between AppDomain and AssemblyLoadContext?

Answer:

AppDomain was used in .NET Framework for isolation and unloading assemblies. In .NET Core/.NET 5+, AssemblyLoadContext replaces it for dynamic loading/unloading without creating separate AppDomains.

34. What does the fixed keyword do in C#?

Answer:

fixed pins a variable in memory, preventing the garbage collector from moving it. This is required for unsafe operations or interop scenarios with unmanaged code.

35. How does string interning affect memory usage in large applications?

Answer:

Interning reduces duplicate string instances, saving memory. However, over-interning or long-lived interned strings can increase memory pressure because interned strings are stored in the intern pool and not collected.

36. How are expression trees used in LINQ, and what is their significance in IQueryable providers?

Answer:

Expression trees represent LINQ queries as data structures, allowing IQueryable providers (e.g., Entity Framework) to translate C# code into queries like SQL. For example:

Expression<Func<int, bool>> expr = x => x > 10;
var query = dbContext.Users.Where(u => u.Age > 10);

The provider translates the expression tree into a database query, optimizing performance.

37. How does the .NET JIT handle method inlining?

Answer:

The JIT uses heuristics (e.g., method size, call frequency) to decide whether to inline. AggressiveInlining can influence the decision, but the JIT may still reject it for various reasons.

38. What’s the difference between volatile and Interlocked operations?

Answer:

volatile guarantees visibility but not atomicity. Interlocked provides atomic operations like Increment or CompareExchange for safe multi-threaded programming.

39. Can you implement IDisposable on a struct? What should you be cautious of?

Answer:

Yes, but you must be cautious because structs are value types. If boxed, disposing the boxed copy won’t affect the original value. Also, avoid fields that require finalization.

40. How do you implement a thread-safe singleton in .NET?

Answer:

The recommended way is using lazy initialization:

public sealed class Singleton {
    private static readonly Lazy instance = new(() => new Singleton());
    public static Singleton Instance => instance.Value;
    private Singleton() {}
}

41. What is the difference between Semaphore and SemaphoreSlim?

Answer:

Semaphore is a wrapper around a Win32 kernel semaphore, suitable for cross-process synchronization. SemaphoreSlim is lighter and intended for use within a single process or app domain.

42. How does .NET’s tiered compilation improve performance?

Answer:

Tiered compilation starts with fast, low-optimized code (Tier 0) for quick startup. It then recompiles frequently used methods with optimizations (Tier 1), improving runtime performance without long initial JIT delays.

43. What is the role of System.Buffers.ArrayPool?

Answer:

ArrayPool provides a shared pool of reusable arrays to reduce GC pressure and allocation cost. It’s especially useful in high-throughput scenarios like serialization or IO operations.

44. Can await Task.Yield() ever block a thread?

Answer:

No. Task.Yield() causes the method to asynchronously yield control back to the caller and ensures that continuation is scheduled later, avoiding blocking.

45. How does ref readonly differ from in parameters?

Answer:

in allows passing by reference with read-only intent at the call site. ref readonly is used in the return signature to allow returning references safely that the caller cannot modify.

46. What is the purpose of ModuleInitializer attribute in C# 9+?

Answer:

ModuleInitializer marks a static method to run before any code in the assembly executes. It is used for setting up state or initializing infrastructure (e.g., logging).

47. What are function pointers and when would you use delegate*?

Answer:

delegate* enables calling unmanaged functions directly, bypassing delegate overhead. Use it in performance-sensitive interop scenarios or when calling C-style function pointers.

48. What are trimming and AOT publishing, and why do they matter?

Answer:

Trimming removes unused code from apps during publish time. AOT compiles apps to native code ahead-of-time. Together, they reduce size and improve startup, especially important for cloud-native and mobile apps.

49. What does Task.WhenAny return and how is it different from Task.WhenAll?

Answer:

Task.WhenAny returns the first task that completes (successfully, faulted, or canceled). Task.WhenAll waits for all tasks to complete and aggregates exceptions, if any.

50. What is the difference between MemoryMarshal and Unsafe.As?

Answer:

MemoryMarshal provides safe access to memory structures (e.g., slicing, casting spans) while maintaining type safety. Unsafe.As allows unchecked type casting with no safety guarantees, often used in extreme performance cases.