Title: Csharp Programming — LearnCoachAssist

Q: What is LINQ in C#?
A: LINQ (Language Integrated Query) is a set of features that allows you to write query expressions directly in C# to filter, sort, and transform data from collections, databases, and XML.
var results = list.Where(x => x > 5).OrderBy(x => x);

Q: What is the difference between LINQ query syntax and method syntax?
A: Query syntax resembles SQL:
var q = from x in list where x > 5 select x;
Method syntax uses extension methods:
var q = list.Where(x => x > 5);
Both compile to the same IL code.

Q: What does the LINQ Select method do?
A: Select projects each element of a sequence into a new form (a transformation/map operation).
var names = people.Select(p => p.Name);
It returns an IEnumerable<T> of the projected type.

Q: What is deferred execution in LINQ?
A: Deferred execution means a LINQ query is not executed when defined, but only when the results are enumerated (e.g., via foreach, ToList(), or Count()). This allows efficient chaining of operations.

Q: How do you use GroupBy in LINQ?
A: GroupBy groups elements by a key:
var groups = students.GroupBy(s => s.Grade);
Each group implements IGrouping<TKey, TElement> with a Key property and a collection of elements.

Q: What is async/await in C#?
A: async/await is a language feature for writing asynchronous code that looks synchronous.
async Task<string> FetchAsync() {
  var data = await httpClient.GetStringAsync(url);
  return data;
}
It frees the calling thread while awaiting I/O operations.

Q: What does the async keyword do in a method signature?
A: The async keyword marks a method as asynchronous, enabling the use of await inside it. It does not make the method run on a separate thread by itself; it allows the compiler to generate a state machine for asynchronous continuations.

Q: What does await do in C#?
A: await asynchronously waits for a Task or Task<T> to complete.
It suspends the method's execution and returns control to the caller until the awaited task finishes, then resumes from where it left off.

Q: What is the difference between Task and Task<T>?
A: - Task represents an asynchronous operation that does not return a value (like void).
- Task<T> represents an asynchronous operation that returns a value of type T.
Use Task for fire-and-forget style async methods and Task<T> when you need a result.

Q: What is a delegate in C#?
A: A delegate is a type-safe function pointer that holds a reference to a method with a specific signature.
delegate int MathOp(int a, int b);
MathOp add = (a, b) => a + b;
Delegates are the foundation for events and callbacks.

Q: What are Action and Func delegates?
A: - Action – a delegate that returns void. E.g., Action<string> log = msg => Console.WriteLine(msg);
- Func – a delegate that returns a value. The last type parameter is the return type. E.g., Func<int, int, int> add = (a, b) => a + b;

Q: What is a multicast delegate?
A: A multicast delegate holds references to multiple methods. When invoked, all methods in the invocation list are called in order.
Action greet = () => Console.Write("Hi ");
greet += () => Console.Write("there!");
greet(); // outputs: Hi there!

Q: What is an event in C#?
A: An event is a mechanism built on delegates that enables a class to notify subscribers when something occurs.
public event EventHandler DataReceived;
Events restrict external code to only subscribe/unsubscribe (+= / -=), preventing direct invocation from outside the declaring class.

Q: What is the difference between a delegate and an event?
A: - A delegate can be invoked by any code that has access to it.
- An event wraps a delegate and restricts invocation to the declaring class only; external code can only subscribe or unsubscribe.
Events provide better encapsulation for the publisher-subscriber pattern.

Q: What is the standard event pattern in C#?
A: The standard pattern uses EventHandler<TEventArgs>:
public event EventHandler<MyEventArgs> OnAction;
protected virtual void RaiseAction(MyEventArgs e) {
  OnAction?.Invoke(this, e);
}
MyEventArgs should derive from EventArgs.

Q: What are generics in C#?
A: Generics allow you to define classes, methods, and interfaces with type parameters, enabling code reuse while maintaining type safety.
List<int> numbers = new List<int>();
Generics eliminate boxing/unboxing overhead and catch type errors at compile time.

Q: What are generic constraints in C#?
A: Generic constraints restrict the types that can be used as type arguments:
- where T : class – reference type
- where T : struct – value type
- where T : new() – parameterless constructor
- where T : IComparable – implements interface
- where T : BaseClass – derives from class

Q: How do you create a generic method in C#?
A: Define the type parameter after the method name:
public T Max<T>(T a, T b) where T : IComparable<T> {
  return a.CompareTo(b) >= 0 ? a : b;
}
The compiler infers T at the call site: Max(3, 7);

Q: What is a property in C#?
A: A property is a member that provides a flexible mechanism to read, write, or compute the value of a private field.
public string Name { get; set; }
Properties use get and set accessors and are preferred over public fields for encapsulation.

Q: What is an auto-implemented property?
A: An auto-implemented property lets the compiler generate the backing field automatically:
public int Age { get; set; }
You can also set access levels: public string Name { get; private set; }
Use init for immutable initialization: public string Id { get; init; }

Q: What is an expression-bodied property?
A: An expression-bodied property uses the => syntax for concise read-only properties:
public string FullName => $"{First} {Last}";
This is equivalent to a get-only property that returns a computed value.

Q: What is an indexer in C#?
A: An indexer allows instances of a class to be indexed like an array:
public T this[int index] {
  get { return items[index]; }
  set { items[index] = value; }
}
You can define indexers with any parameter type, not just int.

Q: What is an extension method in C#?
A: An extension method adds new methods to existing types without modifying them. It must be a static method in a static class, with this before the first parameter:
public static class StringExt {
  public static bool IsEmpty(this string s) => string.IsNullOrEmpty(s);
}

Q: What are the rules for creating extension methods?
A: - Must be in a static class
- Must be a static method
- First parameter must use the this modifier
- The first parameter type is the type being extended
- Must be brought into scope via using directive
Instance methods take precedence over extension methods with the same signature.

Q: What are nullable value types in C#?
A: Nullable value types allow value types to represent null:
int? age = null;
This is shorthand for Nullable<int>. Key members:
- .HasValue – returns true if not null
- .Value – returns the value (throws if null)

Q: What is the null-coalescing operator (??) in C#?
A: The null-coalescing operator returns the left operand if it's not null; otherwise, the right operand:
string name = input ?? "default";
The null-coalescing assignment (??=) assigns only if the left side is null:
name ??= "default";

Q: What is the null-conditional operator (?.) in C#?
A: The null-conditional operator short-circuits to null if the left operand is null:
int? length = text?.Length;
Without it, you'd need an explicit null check. Can be chained:
var city = person?.Address?.City;

Q: What is nullable reference types (NRT) in C#?
A: Nullable reference types (C# 8+) add compile-time null-safety analysis. Enable with #nullable enable.
- string – non-nullable reference
- string? – nullable reference
The compiler warns when you dereference a potentially null reference.

Q: What is pattern matching in C#?
A: Pattern matching tests a value against a pattern and extracts information. Common forms:
- Type pattern: if (obj is string s)
- Constant pattern: if (x is 42)
- Property pattern: if (p is { Age: > 18 })
Used extensively in switch expressions.

Q: How do switch expressions work in C#?
A: Switch expressions (C# 8+) provide a concise syntax:
string result = status switch {
  Status.Active => "Running",
  Status.Paused => "On Hold",
  _ => "Unknown"
};
The _ is the discard pattern acting as a default case.

Q: What are relational and logical patterns in C#?
A: C# 9+ supports relational and logical patterns in switch expressions:
string tier = score switch {
  >= 90 => "A",
  >= 80 and < 90 => "B",
  _ => "C"
};
Logical combinators: and, or, not.

Q: What is a record in C#?
A: A record (C# 9+) is a reference type designed for immutable data with value-based equality:
public record Person(string Name, int Age);
Records auto-generate Equals, GetHashCode, ToString, and support non-destructive mutation with with.

Q: What is the with expression for records?
A: The with expression creates a copy of a record with some properties changed (non-destructive mutation):
var p1 = new Person("Alice", 30);
var p2 = p1 with { Age = 31 };
p1 remains unchanged; p2 is a new instance with Age = 31.

Q: What is the difference between record and record struct?
A: - record (or record class) is a reference type allocated on the heap.
- record struct (C# 10+) is a value type allocated on the stack.
Both provide value-based equality and with expressions, but differ in memory allocation and copy semantics.

Q: What are tuples in C#?
A: Tuples are lightweight data structures for grouping multiple values:
var point = (X: 3, Y: 4);
Console.WriteLine(point.X);
Method return example:
(string Name, int Age) GetPerson() => ("Alice", 30);
Tuples use ValueTuple (value type) under the hood.

Q: How do you deconstruct a tuple in C#?
A: Deconstruction assigns tuple elements to individual variables:
var (name, age) = GetPerson();
You can also deconstruct custom types by implementing a Deconstruct method:
public void Deconstruct(out string name, out int age) { ... }

Q: What is an interface in C#?
A: An interface defines a contract of members that implementing classes must provide:
public interface IShape {
  double Area();
}
Interfaces can contain method signatures, properties, events, and (since C# 8) default implementations. A class can implement multiple interfaces.

Q: What are default interface methods in C#?
A: Default interface methods (C# 8+) allow interfaces to provide method implementations:
public interface ILogger {
  void Log(string msg);
  void LogError(string msg) => Log($"ERROR: {msg}");
}
Implementing classes inherit the default but can override it.

Q: What is explicit interface implementation?
A: Explicit implementation implements an interface member without making it public on the class:
class Printer : IPrintable {
  void IPrintable.Print() { ... }
}
The member is only accessible through the interface reference, useful for resolving naming conflicts between multiple interfaces.

Q: What is the difference between an interface and an abstract class?
A: - Interface: no state (fields), multiple inheritance, defines a contract.
- Abstract class: can have state (fields), constructors, single inheritance, can share implementation.
Use interfaces for capabilities (e.g., IDisposable); use abstract classes for shared base behavior.

Q: What is an abstract class in C#?
A: An abstract class cannot be instantiated and may contain both abstract and concrete members:
public abstract class Shape {
  public abstract double Area();
  public void Describe() => Console.WriteLine($"Area: {Area()}");
}
Derived classes must implement all abstract members.

Q: What is the difference between abstract and virtual methods?
A: - abstract methods have no implementation and must be overridden in derived classes.
- virtual methods have a default implementation that derived classes may optionally override.
Both use the override keyword in derived classes.

Q: What is the sealed keyword in C#?
A: sealed prevents a class from being inherited or a method from being further overridden:
public sealed class Singleton { }
On a method:
public sealed override string ToString() => "fixed";
Sealed classes can offer slight performance benefits due to devirtualization.

Q: What is the IDisposable interface and using statement?
A: IDisposable provides a Dispose() method for releasing unmanaged resources.
The using statement ensures Dispose is called automatically:
using var reader = new StreamReader(path);
string text = reader.ReadToEnd();
Equivalent to a try/finally block calling Dispose.

Q: What is IEnumerable<T> and why is it important?
A: IEnumerable<T> is the base interface for all generic collections that can be enumerated. It requires implementing GetEnumerator().
It enables:
- foreach loops
- LINQ queries
- Deferred execution
Most collection types implement this interface.

Q: What is covariance and contravariance in C# generics?
A: - Covariance (out T) – allows a generic type to be used as a more derived type: IEnumerable<string> → IEnumerable<object>
- Contravariance (in T) – allows a less derived type: Action<object> → Action<string>
Applies to interfaces and delegates.

Q: What is a lambda expression in C#?
A: A lambda expression is an anonymous function using the => operator:
Func<int, int> square = x => x * x;
Multi-statement form:
Func<int, bool> isEven = x => {
  return x % 2 == 0;
};
Lambdas are commonly used with LINQ and delegate parameters.

Q: What is the difference between IEnumerable and IQueryable?
A: - IEnumerable<T> – executes queries in memory (LINQ to Objects). Filtering happens client-side.
- IQueryable<T> – builds expression trees that are translated to a query language (e.g., SQL) and executed server-side.
Use IQueryable with databases for performance; IEnumerable for in-memory collections.

Q: How do you handle exceptions in async methods?
A: Exceptions in async methods are captured in the returned Task. Use try/catch with await:
try {
  await SomeAsyncMethod();
} catch (HttpRequestException ex) {
  Console.WriteLine(ex.Message);
}
Without await, the exception goes unobserved unless the task is inspected.

Q: What is the Aggregate method in LINQ?
A: Aggregate applies an accumulator function over a sequence (similar to reduce/fold):
int sum = numbers.Aggregate((acc, x) => acc + x);
With seed:
string csv = names.Aggregate("", (acc, n) => acc == "" ? n : $"{acc},{n}");
Useful for custom accumulation logic beyond Sum/Count.

Q: What is the difference between string and StringBuilder in C#?
A: string is immutable — every modification creates a new instance in memory, making repeated concatenations expensive (O(n) per append).
StringBuilder is a mutable buffer optimized for repeated modifications, with O(1) amortized appends.
Use string for fixed or rarely-changed text; use StringBuilder when building strings in loops or concatenating many pieces.

Q: What is string interpolation in C#?
A: String interpolation embeds expressions directly into a string using the $ prefix and { } placeholders:
var s = $"Hello, {name}! You are {age} years old.";
Introduced in C# 6. The compiler converts this into a string.Format or DefaultInterpolatedStringHandler call (C# 10+). Use {{ and }} to escape literal braces.

Q: What are raw string literals in C# 11?
A: Raw string literals allow multi-line strings without escaping quotes or special characters. Use three or more double quotes to delimit:
var json = """
  {"name": "Alice", "age": 30}
""";
The number of closing quotes must match or exceed the opening count, allowing embedded " freely.

Q: What is the difference between == and Equals in C#?
A: - == is a compile-time operator. For reference types, it defaults to reference equality; for value types, it compiles to a field-by-field compare if no overload exists.
- Equals is a virtual method on object. The default reference-type implementation does reference equality, but types (like string) override it to do value equality.
Always prefer Equals for value comparison in polymorphic code.

Q: How does string interning work in C#?
A: String interning stores only one copy of each distinct string literal value in a global intern pool. string.Intern(s) adds a string; string.IsInterned(s) retrieves a reference if present.
Interned strings are reference-equal even if created at runtime, so ReferenceEquals returns true for interned values. Useful for memory optimization when many duplicates exist; not generally suitable for untrusted or unbounded data.

Q: What is the difference between StringComparison.Ordinal and StringComparison.CurrentCulture?
A: - Ordinal compares raw Unicode code units — fast, culture-independent, deterministic. Best for internal data, file paths, and security checks.
- CurrentCulture uses the current culture's collation rules — appropriate for user-visible text like sorted lists.
Use OrdinalIgnoreCase for case-insensitive matching of internal identifiers.

Q: What is Span<T> in C#?
A: Span<T> (System.Memory) is a ref struct representing a contiguous region of memory — an array, a slice of a string, or stack-allocated memory. It enables zero-allocation slicing and parsing.
Because it is a ref struct, it cannot be boxed, stored on the heap, or used as an async method parameter. Use ReadOnlySpan<T> for read-only access.

Q: What is the difference between Span<T> and Memory<T>?
A: - Span<T> is a ref struct: stack-only, fast, no async/await use.
- Memory<T> is a regular struct that can live on the heap, be stored in fields, and be passed across await boundaries.
Convert with memory.Span. ReadOnlyMemory<T> provides the read-only counterpart.

Q: What is stackalloc in C#?
A: stackalloc allocates memory on the stack instead of the heap, avoiding GC pressure:
Span<int> buf = stackalloc int[64];
Memory is freed automatically when the method returns. C# 7.2+ allows implicit conversion to Span<T>. Use only for small, short-lived buffers — large stackallocs risk stack overflow.

Q: What is the difference between ref, out, and in parameters?
A: - ref passes by reference; the argument must be initialized before the call, and the method may read and write it.
- out passes by reference; the argument need not be initialized, but the method must assign it before returning.
- in passes by readonly reference — the method cannot modify the argument; avoids a copy for large structs.

Q: What are ref locals and ref returns in C#?
A: Ref locals store a reference to a variable:
ref int r = ref array[i];
Ref returns allow a method to return a reference rather than a value:
public ref int Find(int[] arr, int idx) => ref arr[idx];
These features enable in-place modification of struct fields inside arrays and span-like behavior, with no defensive copies.

Q: How do you use the params keyword in C#?
A: params lets a method accept a variable number of arguments:
int Sum(params int[] numbers) { ... }
Sum(1, 2, 3, 4);
The compiler packs the arguments into an array. Only one params parameter is allowed, and it must be the last parameter. params Span<T> and params ReadOnlySpan<T> are zero-allocation alternatives (C# 13's params collections also allow List<T>, arrays, etc.).

Q: What is a struct in C# and when should you use it?
A: A struct is a value type allocated on the stack (or inline in a containing type) — not on the heap.
Use structs for:
- Small, frequently allocated types
- Types that are logically a single value (e.g., DateTime, Guid)
- Immutable types
Structs cannot inherit from another struct, but can implement interfaces. Large mutable structs hurt performance due to copy semantics.

Q: What is the difference between a struct and a class?
A: - struct – value type, stack-allocated, no inheritance, copied on assignment, default value not null (zero-initialized).
- class – reference type, heap-allocated, supports inheritance, assigned by reference, default value is null.
Boxing occurs when a struct is assigned to a variable of type object or an interface.

Q: What is boxing and unboxing in C#?
A: Boxing wraps a value type (e.g., int) in an object, copying it to the heap:
object o = 42;
Unboxing extracts the value, requiring an explicit cast and a type match:
int n = (int)o;
Boxing and unboxing are expensive operations — avoid in hot paths. Generics (List<T>) eliminate the need for boxing.

Q: What is a ref struct in C#?
A: A ref struct (C# 7.2+) is a struct with the ref modifier that guarantees the type can only live on the stack:
public ref struct ReadOnlySpan<T> { ... }
Constraints: it cannot be a field of a non-ref struct, cannot be in an async method, cannot be boxed, cannot be a type argument. This allows safe use of stack-allocated memory without exposing it to the GC.

Q: What is a static class in C#?
A: A static class is marked with the static keyword and can contain only static members:
public static class MathHelper {
  public static double Pi => 3.14159;
}
It is implicitly sealed and abstract — you cannot instantiate it or derive from it. The compiler prevents non-static members. Use static classes for utility / namespace-like groupings.

Q: What are static constructors in C#?
A: A static constructor initializes a class's static members. It runs once per type, before the first instance is created or any static member is accessed:
class Config {
  static Config() => LoadSettings();
}
It takes no parameters and cannot be called directly. Exceptions thrown here cause TypeInitializationException on every subsequent use of the type.

Q: What is the readonly keyword for fields?
A: A readonly field can be assigned only at declaration or in a constructor:
public readonly int MaxItems;
After construction, the value cannot change. This is different from const, which is baked in at compile time. readonly works with both instance and static fields.

Q: What is the difference between const and readonly?
A: - const is a compile-time constant — its value is inlined into every call site. Allowed only for primitive/string types. public const int Max = 100;
- readonly is a runtime constant — the value can be set in a constructor. Works for any type, including reference types and structs.
Changing a const in a library requires recompiling all assemblies that reference it; readonly does not.

Q: What is the volatile keyword in C#?
A: volatile tells the compiler/JIT that a field may be modified by multiple threads, preventing reordering or caching of reads/writes:
private volatile bool _stopped;
Reads acquire a memory barrier; writes release one. volatile is limited to reference types, pointer types, byte, short, int, char, float, and enum types with those underlying types.

Q: What is the lock keyword and what does it use under the hood?
A: lock ensures exclusive access to a block of code for a single thread:
lock (_sync) { /* critical section */ }
It is syntactic sugar over Monitor.Enter and Monitor.Exit with a try/finally. The locked object should be private, static, and reference-typed. Locking on this, typeof(...), or strings is a known anti-pattern that can cause deadlocks.

Q: What is the difference between Monitor and lock?
A: lock(obj) { ... } expands to:
var b = false;
try { Monitor.Enter(obj, ref b); /* code */ }
finally { if (b) Monitor.Exit(obj); }
Monitor is the underlying primitive. Use lock for the common case. Use Monitor directly when you need TryEnter, Wait, Pulse, or finer control.

Q: What are Concurrent Collections in .NET?
A: Concurrent collections live in System.Collections.Concurrent and are designed for thread-safe access without external locking:
- ConcurrentDictionary<TKey, TValue>
- ConcurrentQueue<T>
- ConcurrentStack<T>
- ConcurrentBag<T>
- BlockingCollection<T>
They use lock-free and fine-grained locking internally for high scalability.

Q: What is the difference between async void and async Task?
A: - async Task is the standard: the returned task can be awaited, exceptions are captured and surfaced.
- async void has no task to await; exceptions go directly to the synchronization context (or crash the process in console apps).
Use async void only for top-level event handlers (UI button clicks). Avoid it in library methods — call sites cannot try/catch properly.

Q: What is Task.WhenAll used for?
A: Task.WhenAll awaits multiple tasks concurrently and returns when all complete:
await Task.WhenAll(task1, task2, task3);
If any task faults, the resulting task contains the exception(s). All tasks start effectively in parallel. Use it for fan-out / fan-in patterns where independent I/O operations can run simultaneously.

Q: What is Task.WhenAny used for?
A: Task.WhenAny returns a task that completes when any one of the supplied tasks completes:
var first = await Task.WhenAny(task1, task2, task3);
Common uses: timeouts, racing multiple sources, or implementing cancellation. Often combined with a delay to bound wait time.

Q: What is CancellationToken and how is it used?
A: CancellationToken propagates cancellation requests through async pipelines:
var cts = new CancellationTokenSource();
var token = cts.Token;
await DoWorkAsync(token);
cts.Cancel();
Cooperative methods periodically check token.IsCancellationRequested or call token.ThrowIfCancellationRequested(), which throws OperationCanceledException.

Q: What is Parallel.ForEach in C#?
A: Parallel.ForEach executes foreach iterations in parallel using multiple threads:
Parallel.ForEach(items, item => Process(item));
It is part of TPL Dataflow / Task Parallel Library. Use for CPU-bound work; for I/O-bound work prefer Task.WhenAll with async. Be cautious with shared state — use Concurrent collections or synchronization.

Q: What is PLINQ in C#?
A: PLINQ (Parallel LINQ) is the parallel version of LINQ. Call .AsParallel() to enable:
var results = data.AsParallel().Where(x => x.Valid).Select(x => x.Value);
The query is partitioned across cores and merged at the end. Use for CPU-bound queries on large data sets; gains diminish for small collections due to partitioning overhead.

Q: What is the Task Parallel Library (TPL)?
A: TPL (System.Threading.Tasks) is the framework for parallel and asynchronous programming in .NET. It centers on the Task type and the Parallel class. Under the hood it uses the thread pool and work-stealing queues for efficient CPU utilization. TPL is the foundation for async/await, Parallel.For, and PLINQ.

Q: What is a Thread vs a Task in C#?
A: - A Thread is a low-level OS thread; creating one is expensive (≈1 MB stack). You manage its lifecycle directly.
- A Task is a higher-level abstraction over work that runs on the thread pool. Creating tasks is cheap; the runtime reuses pool threads.
Prefer Task for almost everything. Use Thread only when you need long-lived, identity-bearing execution (e.g., dedicated background loops with IsBackground).

Q: What is async streaming in C#?
A: Async streams (C# 8) allow await foreach over an IAsyncEnumerable<T>:
async IAsyncEnumerable<int> Stream() {
  while (true) yield return await GetNextAsync();
}
Use it to expose data that arrives over time (network chunks, event batches) without buffering it all. Pair with WithCancellation to honor cancellation tokens.

Q: What is yield return in C#?
A: yield return lets an iterator method produce values one at a time, lazily:
IEnumerable<int> Range(int n) {
  for (int i = 0; i < n; i++) yield return i;
}
The compiler generates a state machine. yield break terminates the iterator early. Each call to GetEnumerator() returns a fresh enumerator.

Q: What are Dictionary<TKey, TValue> lookup complexity?
A: Dictionary<TKey, TValue> provides O(1) average-case lookup, insertion, and deletion using a hash table. Worst case is O(n) when many keys hash to the same bucket, but this is rare with a good hash. TryGetValue is preferred over ContainsKey + indexer to avoid double-hashing. Iteration order is not guaranteed (use SortedDictionary for order).

Q: What is the difference between HashSet<T> and List<T>?
A: - List<T> is an ordered, indexable sequence. Contains is O(n).
- HashSet<T> is an unordered collection of unique items with O(1) Contains, Add, Remove.
Use HashSet for membership tests and deduplication; use List when order and indexing matter.

Q: What is the difference between a shallow copy and a deep copy?
A: - A shallow copy duplicates the top-level object but shares references to nested objects.
- A deep copy recursively duplicates everything, so the clone is fully independent.
MemberwiseClone() makes a shallow copy. record's with expression does a shallow copy. Use serialization, copy constructors, or libraries (e.g., JsonSerializer) for deep copies.

Q: What is the ICloneable interface and why is it controversial?
A: ICloneable declares object Clone(), but the contract does not specify whether it returns a shallow or deep copy — implementations vary. It is widely considered a design mistake; modern APIs avoid it and define explicit copy methods (e.g., CopyTo) or rely on record with-expressions for value-based copies.

Q: What is the IEquatable<T> interface?
A: IEquatable<T> defines bool Equals(T other) for type-safe, allocation-free equality:
struct Point : IEquatable<Point> {
  public bool Equals(Point p) => X == p.X && Y == p.Y;
}
Implement it on value types and on custom types that define value equality. Dictionary and HashSet use it (via EqualityComparer<T>.Default) to avoid boxing.

Q: What is the difference between IComparable and IComparer?
A: - IComparable<T> defines the natural order on the type itself (CompareTo(T other)).
- IComparer<T> is a separate object that defines an alternative ordering (Compare(T a, T b)).
Use IComparable for the default sort; pass an IComparer to List.Sort or OrderBy for different orderings.

Q: What is polymorphism in C#?
A: Polymorphism lets a derived class be treated as its base type. Subtype polymorphism is enabled by virtual/override methods, so the actual runtime type determines which method runs:
Animal a = new Dog();
a.Speak(); // "Woof" if Speak is virtual+overridden
Without virtual, the base implementation runs even for derived instances. C# also has parametric polymorphism (generics) and ad-hoc polymorphism (overloads / operator overloading).

Q: What are operator overloads in C#?
A: You can redefine operators on custom types:
struct Complex {
  public static Complex operator +(Complex a, Complex b) => ...
}
Supported operators include arithmetic (+, -, *), comparison (==, !=, <), and some conversions. The operator must be public static. Overloading == requires also overloading !=, and ideally Equals and GetHashCode.

Q: What is checked vs unchecked arithmetic in C#?
A: - Checked arithmetic throws OverflowException on integer overflow.
- Unchecked (the default) silently wraps around.
Use the checked block or checked() expression to opt in:
int x = checked(a + b);
Project-wide setting via <CheckForOverflowUnderflow>true</CheckForOverflowUnderflow> in the csproj.

Q: What are local functions in C#?
A: Local functions are methods declared inside another method:
void Outer() {
  int Inner(int x) => x * 2;
  Console.WriteLine(Inner(5));
}
They capture variables from the enclosing scope. Unlike lambdas, they can be static (no capture, no closure allocation), generic, and async. They are emitted as real methods, not delegates.

Q: What is the difference between a local function and a lambda?
A: - Local function is a real method; no Delegate is allocated unless you call it through one. It can be static, generic, and have parameter modifiers like ref.
- Lambda compiles to either a delegate (Action/Func) or an expression tree. Captures can create closures that allocate.
Prefer local functions for pure, named subroutines inside methods.

Q: What is a static lambda in C#?
A: A static lambda (static (x, y) => x + y) cannot capture variables from the enclosing scope, so the compiler avoids creating a closure object — a measurable allocation savings in hot paths. C# 9+ allows static on lambdas; C# 12+ allows static on anonymous methods as well.

Q: What is the nameof operator?
A: nameof returns the name of a symbol as a string, with compile-time checking:
ArgumentNullException.ThrowIfNull(arg, nameof(arg));
Renames propagate automatically. Useful in ArgumentException messages, INotifyPropertyChanged callers, and logging. It is evaluated at compile time, so it has zero runtime cost.

Q: What is reflection in C#?
A: Reflection (System.Reflection) lets you inspect and manipulate types at runtime: get properties, methods, attributes, and invoke them dynamically:
var t = typeof(MyClass);
var props = t.GetProperties();
var inst = Activator.CreateInstance(t);
Powerful but slow and unsafe (no compile-time checks). Common in DI containers, ORMs, and serializers. Prefer Source Generators or expression trees for performance-critical paths.

Q: What is the CallerMemberName attribute used for?
A: [CallerMemberName] auto-fills a parameter with the name of the calling member at compile time:
void Raise(string name = "", [CallerMemberName] string caller = "") => ...
Common in INotifyPropertyChanged implementations so you don't repeat property names as strings. Related: [CallerFilePath], [CallerLineNumber].

Q: What is the difference between dynamic and object?
A: - object is statically typed; the compiler enforces member access (you'd need to cast to call members).
- dynamic bypasses compile-time checks; member calls are resolved at runtime via the DLR (Dynamic Language Runtime), using IDynamicMetaObjectProvider or ExpandoObject.
Use dynamic sparingly — for COM interop, dynamic JSON, or interop with dynamic languages.

Q: What is dependency injection in ASP.NET Core / .NET?
A: DI is a first-class citizen in modern .NET. You register services in Program.cs:
builder.Services.AddScoped<IUserService, UserService>();
And inject them via constructors:
public UsersController(IUserService svc) { _svc = svc; }
Built-in lifetimes: Singleton (one per app), Scoped (one per request), Transient (new each time). Third-party containers (Autofac, Lamar) extend this with features like property injection and keyed services.

Q: What is the difference between IOptions and IOptionsSnapshot?
A: - IOptions<T> is a singleton — reads configuration once at startup; values do not change for the lifetime of the app.
- IOptionsSnapshot<T> is scoped — re-reads configuration per request, so changes to appsettings.json are picked up on the next request.
- IOptionsMonitor<T> is a singleton that watches for changes and raises a callback.

Q: What is a memory leak in managed C# code?
A: In .NET, memory leaks are not about forgetting to free memory (the GC does that) — they are about references that the GC cannot see as unreachable:
- Static fields holding object graphs
- Event handlers not unsubscribed
- Unbounded caches
- Captured closures in long-lived objects
- IDisposable not disposed (especially with unmanaged resources)
Diagnose with dotMemory, PerfView, or GC.GetTotalMemory(true).

Q: What are weak references in C#?
A: WeakReference allows you to hold a reference to an object without preventing GC:
var weak = new WeakReference(obj);
if (weak.TryGetTarget(out var t)) { ... }
Used in caches, listeners, and to break reference cycles. The GC can collect the object at any time, so always check TryGetTarget before use. WeakReference<T> is the type-safe variant.

Q: What is the IDisposable pattern and the dispose pattern?
A: For classes holding unmanaged resources, implement IDisposable and follow the dispose pattern:
public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); }
protected virtual void Dispose(bool disposing) { /* free unmanaged; if (disposing) free managed */ }
~MyClass() { Dispose(disposing: false); }
Callers use using; finalizer is a safety net. The modern alternative is to avoid finalizers by using SafeHandle.

Q: What is the difference between Finalize and Dispose?
A: - Dispose is called explicitly by user code (typically via using) — runs deterministically.
- Finalize (destructor) is called by the GC at some point after the object becomes unreachable — non-deterministic, expensive (objects survive an extra GC cycle).
Implement Dispose for prompt cleanup. Finalize is a last-resort safety net and should not allocate or reference other managed objects.

Q: What is a global using directive?
A: C# 10 introduced global usings — a single global using applies to every file in the project:
global using System.Linq;
Common in .NET 6+ projects that auto-emit common ones (System, System.Collections.Generic, System.IO, System.Linq, System.Net.Http, System.Threading, etc.).

Q: What is the throw expression in C# 7?
A: throw can now appear in expressions, not just statements:
var name = dict.TryGetValue(id, out var v) ? v : throw new KeyNotFoundException(id);
Useful in conditional operators, switch expressions, expression-bodied members, and null-coalescing:
name = input ?? throw new ArgumentNullException(nameof(input));

Q: What is the null-forgiving operator (!) in C#?
A: The null-forgiving operator (!) suppresses nullable-reference-type warnings:
string s = GetPossiblyNull()!; // "trust me, it's not null"
It performs no runtime check — if the value really is null, you'll still get a NullReferenceException later. Use it sparingly, at trust boundaries (e.g., right after a manual null check, or for EF entity properties that the framework initializes).

Q: What are required members in C# 11?
A: The required modifier forces callers to set certain properties at construction time:
public class Person {
  public required string Name { get; init; }
}
var p = new Person { Name = "Alice" }; // OK
var p2 = new Person(); // compile-time error
The compiler enforces this at new and with object-initializer syntax, removing the need for verbose constructor parameters for settings objects.

Q: What is the C# 9 init-only property?
A: init accessors allow properties to be set only during object initialization:
public string Name { get; init; }
After construction, the property is effectively immutable. This is the modern alternative to read-only fields for init-only DTOs and is supported in object initializers and with expressions.

Q: What are primary constructors in C# 12?
A: Primary constructors let you declare constructor parameters on the type itself, automatically making them captured into the body:
public class Person(string name, int age) {
  public string Name { get; } = name;
}
Parameters are in scope for the entire class body, removing the boilerplate of explicit field declaration and constructor assignment. Available on classes, structs, and records.

Q: What is collection expression syntax in C# 12?
A: Collection expressions unify array, list, and span literals:
int[] arr = [1, 2, 3];
List<string> names = ["Alice", "Bob"];
Span<int> s = [4, 5, 6];
The compiler picks the best target type. Supports the spread operator ..:
int[] combined = [..arr, ..other];

Q: What are index from-end and range operators?
A: - Range ^n means "from the end": arr[^1] is the last element.
- Range a..b is a slice: arr[1..3] gives elements 1 and 2.
- Combined: arr[^2..] is the last two.
Types support these by exposing an int-indexer (for ^) and a Range-indexer (for ..). Built-in for arrays, Span<T>, string, and List<T>.

Q: What is the difference between var and dynamic?
A: - var is statically typed; the compiler infers the type at compile time, and the variable is bound to that type forever.
- dynamic bypasses compile-time checks entirely — member calls are resolved at runtime.
var improves readability and gives IntelliSense. dynamic is for interop with dynamic languages or late-bound APIs.

Q: What is the difference between is and as operators?
A: - is tests whether an object is of a given type: if (obj is string s). It returns bool and (with the pattern form) can extract the value.
- as attempts a safe cast: var s = obj as string;. It returns null on failure (for reference types and nullable value types) instead of throwing InvalidCastException.
Use is for branching; use as when a null result is acceptable.

Q: What is the difference between Convert.ToInt32 and (int)?
A: - Convert.ToInt32(d) rounds double values using banker's rounding (to even).
- (int)d on a double truncates toward zero.
Also, Convert.ToInt32(null) returns 0, while (int)null won't compile. Use Convert for cross-type safe conversions.

Q: What are the C# preprocessor directives?
A: - #define / #undef — define/undefine a symbol
- #if / #elif / #else / #endif — conditional compilation
- #nullable enable / #nullable disable / #nullable restore — nullable annotation context
- #region / #endregion — collapsible editor regions
- #pragma warning disable / #pragma warning restore — suppress compiler warnings
- #line — adjust line numbers in error messages
- #error / #warning — emit a compile error or warning
Note: preprocessor directives are processed by the C# compiler — the underlying language has no preprocessor.

Q: What are the access modifiers in C#?
A: - public — accessible everywhere
- private — only within the containing type
- protected — within the type and derived types
- internal — within the same assembly
- protected internal — within the same assembly or derived types
- private protected — within the same assembly and derived types (C# 7.2+)
- file — within the same source file (C# 11)
Default for top-level types is internal; default for members is private.

Q: What is the difference between internal and protected internal?
A: - internal — accessible anywhere in the same assembly.
- protected internal — accessible in the same assembly OR in any derived class (even in other assemblies). It is a union of protected and internal.
- private protected — accessible only in the same assembly AND in derived types. It is an intersection of protected and internal.

Q: What is an assembly in C#?
A: An assembly is the compiled output of a project — a DLL or EXE. It contains IL code, metadata, and a manifest. The unit of versioning, security, and deployment. C# does not have a separate "module" file like C++ — multiple assemblies are linked at runtime. internal access is restricted to the same assembly.

Q: What are partial classes in C#?
A: The partial keyword allows a class (or struct, interface, or record) to be split across multiple files:
public partial class User { ... } // in User.cs
public partial class User { ... } // in User.Queries.cs
All parts are merged at compile time. Common in code generation (WinForms designer, EF), large feature files, and separating hand-written from generated code. All parts must use the same access modifier and base classes.

Q: What is a frozen collection in .NET?
A: FrozenCollection types (System.Collections.Frozen, .NET 8+) are immutable, optimized-for-read collections:
var lookup = items.ToFrozenDictionary(x => x.Id);
They are slower to build but faster to read than Dictionary/ImmutableDictionary for lookup-heavy scenarios. Use when the collection is built once and read many times (configuration, lookup tables).

Q: What is the System.Text.Json source generator?
A: The JsonSerializer source generator emits the serialization code at compile time, eliminating reflection:
[JsonSerializable(typeof(MyDto))]
partial class AppContext : JsonSerializerContext { }
Benefits: faster startup, smaller binary, AOT-friendly, trimmed apps work. It is the recommended serializer for new .NET projects over Newtonsoft.Json.

Q: What is the difference between JIT and AOT compilation?
A: - JIT (Just-In-Time) compiles IL to native code at runtime, on demand, with knowledge of the actual machine. Default for .NET.
- AOT (Ahead-Of-Time) compiles to native code at build time, producing a single-file, platform-specific binary with no JIT. Faster startup, smaller memory, but no runtime code generation or dynamic loading.
AOT is great for serverless, CLI tools, and mobile (iOS).

Q: What is the IAsyncDisposable interface?
A: IAsyncDisposable (.NET Core 3.0+) is the async counterpart of IDisposable:
public async ValueTask DisposeAsync() { await FlushAsync(); }
Use it when cleanup involves async I/O (flushing buffers, closing network connections). The await using statement disposes asynchronously. Many types implement both — the runtime calls DisposeAsync when used with await using.

Q: What is the difference between Array.Length and Array.Count()?
A: - arr.Length is a property on arrays; O(1).
- arr.Count() is a LINQ extension method that walks the sequence and returns the count — O(n) for arrays, O(1) for ICollection via the Count property.
Prefer .Length for arrays; prefer .Count on IEnumerable<T> when you don't know the concrete type.

Q: What is the difference between Stopwatch and DateTime for measuring time?
A: - DateTime.UtcNow has ~10–15 ms resolution and can jump if the system clock changes.
- System.Diagnostics.Stopwatch uses a high-resolution monotonic counter, suitable for benchmarking:
var sw = Stopwatch.StartNew();
DoWork();
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);

Q: What is the difference between BackgroundService and IHostedService?
A: BackgroundService is a base class that simplifies IHostedService — you implement ExecuteAsync and the base class handles start/stop and graceful shutdown:
class MyWorker : BackgroundService {
  protected override async Task ExecuteAsync(CancellationToken stop) { while (!stop.IsCancellationRequested) await DoWork(); }
}
Default for new background work.

Q: What is the difference between throw and throw ex in C#?
A: - throw; — re-throws the original exception, preserving the stack trace.
- throw ex; — throws the same exception object but resets the stack trace to the current line, losing the original call site information.
Always use bare throw; in catch blocks unless you intentionally want to obscure the origin (rare).

Q: What is a using declaration vs using statement (in C# 8+)?
A: - using statement (classic):
using (var r = new Resource()) { ... } — disposes at end of the using block.
- using declaration:
using var r = new Resource(); — disposes at end of the enclosing scope (method, block).
Both ensure Dispose is called. The declaration form reduces indentation and works well with async.

Q: What is the difference between Environment.NewLine and "\n"?
A: - "\n" is LF — Unix/macOS.
- "\r\n" is CRLF — Windows.
- Environment.NewLine is the platform-appropriate line separator for the current OS.
Use Environment.NewLine for user-facing output on a single platform; for cross-platform files (logs, exports), pick one explicitly and document it.

Q: What is lazy initialization in C#?
A: Lazy<T> defers creation of a value until first access, in a thread-safe way:
var lazy = new Lazy<Expensive>(() => new Expensive());
var v = lazy.Value; // constructed on first access
Use Lazy<T> for expensive objects, singletons, or breaking initialization cycles. Variants: LazyThreadSafetyMode.ExecutionAndPublication (default), PublicationOnly, None.

Q: What is a thread-local storage in C#?
A: ThreadLocal<T> and AsyncLocal<T> give you per-context state:
- ThreadLocal<T> — value is unique per OS thread. Bad with async (continuations can run on different threads).
- AsyncLocal<T> — value flows with the async control flow. Used for HttpContext, CallContext, ambient context.
Use AsyncLocal for ambient values in async code.

Q: What is the difference between Task.Delay and Thread.Sleep?
A: - Thread.Sleep(1000) blocks the current thread for 1 second — it cannot do anything else.
- await Task.Delay(1000) yields the thread back to the pool for 1 second — the thread is free to do other work.
Use Task.Delay in async methods to avoid blocking threads and to keep the thread pool responsive.

Q: What is a record class positional vs record struct?
A: - public record Person(string Name, int Age); — positional record on a reference type. Immutable by default, value equality.
- public readonly record struct Point(int X, int Y); — positional record on a value type. Stack-allocated, no allocation, value equality.
Use the readonly modifier on record struct to prevent defensive copies.

Q: What is the difference between new() constraint and class constraint?
A: - where T : new() — the type argument must expose a public parameterless constructor. The compiler can then new T() inside the generic.
- where T : class — the type argument must be a reference type; no constructor is required.
You can combine them: where T : class, new().

Q: What is the difference between Func and Predicate<T>?
A: - Predicate<T> — bool Predicate(T obj). Special-cased for collection filtering (List<T>.Find, Array.FindAll).
- Func<T, bool> — same signature as Predicate<T> but a generic form used in LINQ (Where, Any, All).
Predicate<T> is largely historical; prefer Func<T, bool> in new code.

Q: What is the difference between Array and List<T>?
A: - Array (e.g., int[]) — fixed size, allocated in one block, very low overhead. Slicing requires Array.Copy or Span<T>.
- List<T> — dynamically resizable, backed by an array that doubles when full. Add is amortized O(1); Insert/RemoveAt are O(n).
Use arrays for fixed-size, hot-path data; use List<T> when you need to grow/shrink.

Q: What is encoding and decoding in C#?
A: Encoding converts between char sequences (UTF-16) and byte sequences:
- Encoding.UTF8.GetBytes(s) — string to bytes
- Encoding.UTF8.GetString(bytes) — bytes to string
Always specify the encoding explicitly. Encoding.UTF8 is the safest default. The Encoding.Default is the system's ANSI code page and should be avoided in cross-platform code.

Q: What is the difference between Array.Copy and Array.ConstrainedCopy?
A: - Array.Copy may fall back to a slower path if source and destination overlap; it tolerates ArrayTypeMismatchException.
- Array.ConstrainedCopy requires non-overlapping regions and identical element types; guarantees atomic copy on a best-effort basis. Throws if the constraint is violated.
Use ConstrainedCopy in CERs (constrained execution regions) or safety-critical code.

Q: What is the difference between StringBuilder and string.Create?
A: - StringBuilder builds a string through repeated appends; the final ToString() allocates a new string.
- string.Create(length, state, action) (C# 10+) creates a string with a known final length, filling a backing Span<char> directly. No intermediate buffer.
Use string.Create when you know the exact size of the result — it is the fastest way to format a string in .NET 6+.

Q: What is the difference between string.IsNullOrEmpty and string.IsNullOrWhiteSpace?
A: - string.IsNullOrEmpty(s) returns true if s is null or "".
- string.IsNullOrWhiteSpace(s) also returns true for strings containing only whitespace (spaces, tabs, newlines).
Use IsNullOrWhiteSpace for user input validation.

Q: What is ArgumentException.ThrowIfNull and other throw-helpers?
A: .NET 6+ ships throw helpers to reduce boilerplate validation:
- ArgumentNullException.ThrowIfNull(arg)
- ArgumentException.ThrowIfNullOrEmpty(arg)
- ArgumentException.ThrowIfNullOrWhiteSpace(arg)
Pass paramName: and message: as needed. Prefer them over hand-rolled if (x == null) throw ....

Q: What is the difference between throw and ExceptionDispatchInfo.Throw?
A: ExceptionDispatchInfo.Throw(ex) rethrows an exception preserving the original stack trace, even across threads or async boundaries:
ExceptionDispatchInfo.Capture(ex).Throw();
Useful when capturing an exception in one task and rethrowing it after awaiting, where the original stack trace would otherwise be lost.

Q: What is the difference between Mutex and SemaphoreSlim?
A: - Mutex — single-owner lock, can be named and cross-process. Used to ensure only one instance of an app runs.
- SemaphoreSlim — in-process, allows N concurrent holders. Lightweight.
For cross-process coordination, use Mutex or Semaphore (the full-fat version). For in-process, prefer SemaphoreSlim.

Q: What is ILogger and why is it preferred?
A: ILogger<T> (Microsoft.Extensions.Logging) is the standard logging abstraction. It supports structured logging, levels (Trace, Debug, Info, Warning, Error, Critical), and providers (Console, Debug, Serilog, Application Insights, etc.).
_logger.LogInformation("Processed {Count} items in {ElapsedMs}ms", count, ms);
Inject ILogger<T> via DI; do not use Console.WriteLine in production code.

Q: What is the difference between Exception.Data and InnerException?
A: - InnerException is a single, conventional wrapped exception (typical in TargetInvocationException, AggregateException).
- Exception.Data is a free-form IDictionary for arbitrary context (e.g., request IDs, user IDs) attached to an exception.
Use Data["RequestId"] = id for telemetry, and throw new MyException("msg", innerEx) to wrap a cause.

Q: What is the difference between sealed class and static class?
A: - sealed class — can be instantiated, but cannot be inherited. Fields, instance methods, and constructors are allowed.
- static class — cannot be instantiated or inherited. Only static members are allowed. Implicitly sealed and abstract.
Use static for utility namespaces; use sealed to lock down a regular class that should not be derived from.

Q: What are top-level statements in .NET 6+?
A: Top-level statements let you write Program.cs without the boilerplate class Program { static void Main() { ... } }:
// Program.cs
Console.WriteLine("Hello!");
Behind the scenes, the compiler synthesizes a Main. Only one file in a project can have top-level statements. Combined with global usings, this makes tiny apps and demos very compact.

Q: What is the difference between ReadOnly and Immutable collections?
A: - Read-only collections (ReadOnlyCollection<T>, IReadOnlyList<T>) — wrappers around a mutable collection. The interface prevents mutation, but the underlying collection can still change.
- Immutable collections (System.Collections.Immutable) — truly immutable trees; every modification returns a new instance with structural sharing.
Use immutable collections in concurrent code or when you need real immutability.

Q: What is the difference between FrozenSet and ImmutableHashSet?
A: - ImmutableHashSet supports Add/Remove returning a new set with structural sharing. Optimized for general use.
- FrozenSet (.NET 8+) supports read-only access only, but is optimized for lookups over a build-once set. Builds slowly; reads very fast.
Pick FrozenSet for config tables, lookup dictionaries, and read-heavy hot paths.

Q: What is the difference between StringComparer.Ordinal and StringComparer.InvariantCulture?
A: - StringComparer.Ordinal — compares code points, fast, culture-independent.
- StringComparer.InvariantCulture — applies invariant culture collation rules, slower, but linguistically consistent across machines.
For dictionaries/hashtables of identifiers, headers, paths: Ordinal. For user-visible sorting and display: InvariantCulture (or CurrentCulture if the result is for the current user only).

Q: What is the difference between File.ReadAllText and File.ReadAllLines?
A: - File.ReadAllText(path) returns the entire file as a single string.
- File.ReadAllLines(path) returns a string[], one element per line.
For large files, use streaming: File.OpenText + StreamReader or File.ReadLines(path) (lazy IEnumerable<string>).

Q: What is the difference between struct equality and reference equality?
A: - Two struct instances with the same field values are value-equal. Equals checks fields (or your override).
- Two class instances with the same field values are not value-equal by default — Equals uses reference equality unless overridden (or unless the type is a record).
Use record or override Equals/GetHashCode on classes that should compare by value.

Q: What is the difference between SortedList and SortedDictionary?
A: - SortedList<TKey, TValue> — backed by a sorted array. O(log n) lookup, but O(n) insert/remove (shifts).
- SortedDictionary<TKey, TValue> — backed by a red-black tree. O(log n) for all operations, but higher memory overhead per node.
Use SortedList when inserts are rare and lookups dominate; SortedDictionary for balanced insert/lookup patterns.

Q: What is the difference between Single, SingleOrDefault, First, and FirstOrDefault?
A: - First — returns the first element; throws if empty.
- FirstOrDefault — returns the first element or default(T) if empty.
- Single — returns the only element; throws if there are zero or more than one.
- SingleOrDefault — returns the only element, default(T) if empty, throws if more than one.
Use Single when you expect exactly one match; it makes the invariant explicit.

Q: What is the difference between ToList and ToArray?
A: - ToList returns a List<T> — mutable, dynamically resizable, supports Add/Remove.
- ToArray returns a T[] — fixed size, lower overhead, immutable from the caller's perspective.
Both are O(n) and force enumeration. Prefer ToArray if you need an immutable snapshot; prefer ToList if you need to grow.

Q: What is the difference between Cast and OfType in LINQ?
A: - Cast<T> — casts every element to T; throws InvalidCastException on the first non-T element.
- OfType<T> — keeps only elements that are T, skipping the rest.
Use OfType when filtering a non-generic collection (ArrayList, IEnumerable from a legacy API) for items of a specific type.

Q: What is the difference between Zip and Join in LINQ?
A: - Zip(a, b, (x, y) => ...) — pairs elements by position. Stops at the shorter sequence.
- a.Join(b, x => x.Key, y => y.Key, (x, y) => ...) — pairs by a key. Like SQL INNER JOIN.
Use Zip for parallel arrays; use Join for relational merges.

Q: What is the difference between SelectMany and nested Select?
A: - orders.Select(o => o.Items) returns IEnumerable<IEnumerable<Item>>.
- orders.SelectMany(o => o.Items) flattens to a single IEnumerable<Item>.
SelectMany is essential for one-to-many projections and chaining inner queries.

Q: What is ArrayPool<T> in .NET?
A: ArrayPool<T>.Shared rents and returns pre-allocated arrays from a shared pool:
var buf = ArrayPool<byte>.Shared.Rent(1024);
try { /* use buf */ } finally { ArrayPool<byte>.Shared.Return(buf); }
Useful in I/O paths to avoid repeated allocations. Span<T> can wrap the rented array for zero-copy slicing.

Q: What is the difference between is null and == null?
A: - x is null — a constant pattern; never invokes user-defined == operators. The compiler generates a true/false based on the actual null state.
- x == null — invokes the operator, which the type may have overloaded (e.g., Nullable<T>, custom ==).
For reference-type null checks, prefer is null to avoid surprising operator overloads. For nullable value types, use HasValue or == null (operator-aware).

Q: What is a list pattern in C# 11?
A: List patterns match sequences against a pattern:
var s = numbers switch {
  [1, 2, ..] => "starts with 1, 2",
  [_, _, _] => "exactly 3 elements",
  [] => "empty",
  _ => "other"
};
The .. slice pattern matches zero or more elements. Pairs well with Span<T> and arrays for parsing.

Q: What is a verbatim string and when is it used?
A: Verbatim strings (prefix @) disable escape processing and allow multi-line text:
var path = @"C:\Users\Alice\file.txt";
var multi = @"line 1
line 2";
To include a ", double it: @"He said ""hi"".". Combine with $ for interpolated verbatim strings: $@"Path: {path}".

Q: What is the difference between an async method and a TaskCompletionSource?
A: TaskCompletionSource<T> lets you create a Task<T> you can manually complete, fail, or cancel from non-async code:
var tcs = new TaskCompletionSource<int>();
// later...
tcs.SetResult(42);
Use it to wrap callback-based APIs (events, IAsyncResult patterns) into awaitable tasks without an async method.

Q: What is the difference between IObserver and IObservable?
A: - IObservable<T> — a source of a stream of values; subscribes an IObserver<T>.
- IObserver<T> — a subscriber with OnNext, OnError, OnCompleted.
Rx.NET (System.Reactive) is the canonical implementation. For one-off Task-returning async streams, prefer IAsyncEnumerable<T>.

Q: What is the difference between EventHandler and Action?
A: - EventHandler — void (object sender, EventArgs e). Standard signature for .NET events.
- Action — void (). A simple delegate with no parameters.
Events conventionally use EventHandler (or EventHandler<T>) so that subscribers receive the sender and the event payload. Use Action for general callbacks (e.g., Timer constructors).

Q: What is the difference between Lazy<T> and LazyInitializer?
A: - Lazy<T> wraps initialization in an object with a Value property; thread-safety modes are configurable.
- LazyInitializer.EnsureInitialized(ref _field, () => new T()) — extension method that initializes a field in place, with optional double-checked locking.
For single-field lazy singletons, LazyInitializer is slightly more memory-efficient (no wrapper object).

Q: What is the difference between DateTime and DateTimeOffset?
A: - DateTime stores a date and time with a Kind of Unspecified, Utc, or Local. The same DateTime can refer to different moments depending on its Kind.
- DateTimeOffset stores a date/time plus an explicit offset from UTC, unambiguously identifying a single point in time. Comparison and arithmetic use UTC.
For server-side code, time-zone math, and persistence, prefer DateTimeOffset to avoid Kind-related bugs.