C#/.NET Fundamentals Interview Questions

50 questions and answers covering C#/.NET Fundamentals, from fundamentals through practical, debugging, and design-level topics.

50 of 50 interview questions

  1. What is the relationship between C# and .NET?beginnerC# & .NET Fundamentals

    C# is a programming language; .NET is the runtime/platform (including the base class library and the Common Language Runtime) that C# code compiles down to and executes on -- .NET also supports other languages (F#, VB.NET) that all compile to the same intermediate language and run on the same runtime.

  2. Is C# compiled or interpreted, and what role does the CLR (Common Language Runtime) play?intermediateC# & .NET Fundamentals

    C# is compiled to an intermediate language (IL), not directly to native machine code -- the CLR then Just-In-Time (JIT) compiles that IL to native code at runtime, similar in spirit to Java's JVM/bytecode model, giving both portability across platforms and near-native runtime performance.

  3. What is string interpolation in C#, and what does the `$"..."` syntax offer over plain concatenation?beginnerC# & .NET Fundamentals

    String interpolation embeds expressions directly inside a string literal (`$"Hello, {name}!"`), evaluated at runtime -- more readable than manually concatenating strings with `+`, and avoids the positional-argument confusion of older `string.Format`-style indexed slots.

    string name = "Asha";
    Console.WriteLine($"Hello, {name}!");
  4. What is the difference between a value type and a reference type in C#, using `int` and a class as examples?intermediateC# & .NET Fundamentals

    A value type (like `int`, `struct`) stores its actual data directly and is copied by value when assigned or passed; a reference type (like a `class` instance) stores a reference to data on the heap, so assignment copies the reference, not the underlying object -- two variables can then refer to the SAME underlying object.

  5. Does C# have automatic memory management, and how does that compare to C/C++'s manual approach?intermediateC# & .NET Fundamentals

    Yes -- the CLR includes a garbage collector that automatically reclaims memory for objects no longer reachable, similar to Java's model -- developers generally don't manually free memory, unlike C/C++'s explicit `malloc`/`free` or `new`/`delete`.

  6. What is the difference between `==` and `.Equals()` for comparing two reference-type objects in C#?advancedC# & .NET Fundamentals

    By default, `==` on reference types compares REFERENCE identity (are these the same object in memory) unless the type overrides the `==` operator; `.Equals()` is meant for value equality and is commonly overridden by custom types to compare actual content -- built-in types like `string` override both to compare content by default.

  7. What is the difference between `switch` statement and `switch` expression syntax in modern C#?advancedC# & .NET Fundamentals

    A `switch` statement executes code per matched case (with `case`/`break` syntax); a `switch` expression (`var result = value switch { 1 => "one", _ => "other" };`) directly evaluates to a value using more concise pattern-matching arrow syntax -- the expression form is more common in modern, idiomatic C# for simple value-mapping logic.

  8. What does the `var` keyword do in C#, and is C# still statically typed when you use it?beginnerC# & .NET Fundamentals

    `var` lets the compiler infer a local variable's type from its initializer -- the variable's type is still fixed and checked at COMPILE time, exactly as if you'd written the type explicitly; `var` is purely a syntax convenience, not a move toward dynamic typing.

  9. What is boxing and unboxing in C#, and why can excessive boxing hurt performance?advancedC# & .NET Fundamentals

    Boxing converts a value type (like `int`) into a reference-type object (wrapping it on the heap); unboxing converts it back -- each boxing operation allocates new heap memory and adds garbage-collection pressure, so code that boxes value types frequently (e.g. storing many `int`s in a non-generic `ArrayList`) can incur real, avoidable overhead.

  10. Why is C# widely used across both enterprise backend systems (via ASP.NET) and game development (via Unity)?intermediateC# & .NET Fundamentals

    It combines strong tooling (Visual Studio, a rich standard library), solid performance via the CLR's JIT compilation, and a large ecosystem -- ASP.NET provides a mature web framework for backend services, while Unity adopted C# as its primary scripting language, giving the language reach across genuinely different domains.

  11. What is a C# property, and how does it differ from a plain public field?beginnerObject-Oriented C#: Classes, Interfaces & Encapsulation

    A property (`public string Name { get; set; }`) exposes a controlled accessor/mutator pair while looking like simple field access from the caller's perspective -- unlike a plain public field, a property can later add validation logic in its getter/setter without breaking the calling code's syntax.

    public class User {
      public string Name { get; set; }
    }
  12. What does an auto-implemented property (`{ get; set; }` with no explicit backing field) actually do behind the scenes?intermediateObject-Oriented C#: Classes, Interfaces & Encapsulation

    The compiler automatically generates a hidden, private backing field and the standard get/set logic for you -- convenient shorthand for the common case where a property doesn't need any custom validation logic beyond simple storage.

  13. What is the difference between a class and an interface in C#, and can a class implement multiple interfaces?intermediateObject-Oriented C#: Classes, Interfaces & Encapsulation

    A class can hold state and provide full implementations; an interface (traditionally) declares a contract of members a class must implement, with no state of its own -- a C# class can implement MULTIPLE interfaces but can only inherit from ONE base class (C# has single class inheritance).

  14. What does the `virtual` keyword on a method allow, and how does `override` relate to it in a derived class?advancedObject-Oriented C#: Classes, Interfaces & Encapsulation

    `virtual` marks a method as overridable by a derived class; the derived class then uses `override` to provide its own implementation -- calling the method through a base-class-typed reference still dispatches to the derived class's overridden version at runtime, C#'s mechanism for polymorphism.

  15. What are the standard C# access modifiers, and what does `internal` specifically restrict access to?advancedObject-Oriented C#: Classes, Interfaces & Encapsulation

    `public`, `private`, `protected`, `internal`, and `protected internal` -- `internal` restricts access to code within the SAME assembly (compiled project/DLL), useful for exposing something to other classes in the same project while hiding it from external consumers of that assembly.

  16. What is the difference between an `abstract` class and an interface in C#?advancedObject-Oriented C#: Classes, Interfaces & Encapsulation

    An abstract class can provide both abstract (unimplemented) and concrete (implemented) members plus real instance state, and can only be single-inherited; an interface (traditionally) declares only a contract with no state, and a class can implement many -- choose an abstract class when sharing real implementation/state across related types, an interface when only defining a capability contract.

  17. What does a C# constructor do, and how do you chain one constructor to call another in the same class?intermediateObject-Oriented C#: Classes, Interfaces & Encapsulation

    A constructor initializes a newly-created object's state -- `: this(...)` lets one constructor overload delegate to another in the same class, avoiding duplicated initialization logic across multiple constructor overloads.

    public User(string name) : this(name, 0) {}
    public User(string name, int age) { Name = name; Age = age; }
  18. What is a C# record type, and what problem does it solve compared to a regular class for simple data-holding types?advancedObject-Oriented C#: Classes, Interfaces & Encapsulation

    A record provides built-in value-based equality, a readable `ToString()`, and concise immutable-by-default property syntax -- solves the boilerplate of manually implementing `Equals`/`GetHashCode`/`ToString` for a simple data-holding type where structural (not reference) equality is the natural expectation.

  19. Why is encapsulation (using properties/private fields rather than exposing everything as public fields) still emphasized in modern C#, even with concise auto-property syntax?intermediateObject-Oriented C#: Classes, Interfaces & Encapsulation

    Properties let you add validation or computed logic later without changing the class's public interface (callers keep using the same `obj.Name` syntax) -- a plain public field offers no such extension point, so starting with a property (even a trivial auto-property) keeps that flexibility available from the start.

  20. What is the difference between method overloading and method overriding in C#?advancedObject-Oriented C#: Classes, Interfaces & Encapsulation

    Overloading defines multiple methods with the SAME name but different parameter signatures within the same class, resolved at compile time; overriding replaces a base class's `virtual` method implementation in a derived class, resolved at runtime based on the object's actual type -- two genuinely different mechanisms, both sometimes casually called 'polymorphism.'

  21. What are nullable reference types in modern C#, and what problem do they solve?advancedNullable Reference Types, LINQ & Collections

    With nullable reference types enabled, the compiler tracks and warns when a reference-type variable that ISN'T explicitly marked nullable (`string?` vs. plain `string`) might be assigned or passed `null` -- surfaces a real class of `NullReferenceException` risk as a compile-time warning instead of a runtime crash.

    string? maybeName = GetName();  // explicitly nullable
    string name = GetName();        // compiler warns if this could be null
  22. What does the null-conditional operator (`?.`) do, and how does it differ from a plain `.` access?intermediateNullable Reference Types, LINQ & Collections

    `obj?.Property` accesses the property only if `obj` is not `null`, otherwise short-circuits to `null` instead of throwing -- replaces verbose manual null-checking chains (`if (obj != null) { ... }`) with a single, concise expression.

    string? city = user?.Address?.City;
  23. What does the null-coalescing operator (`??`) do, and how does `??=` differ from it?intermediateNullable Reference Types, LINQ & Collections

    `a ?? b` evaluates to `a` if it's not `null`, otherwise `b` -- a concise default-value expression; `a ??= b` assigns `b` to `a` only if `a` is currently `null`, a combined null-check-and-assign shorthand.

  24. What is LINQ (Language Integrated Query), at a conceptual level?intermediateNullable Reference Types, LINQ & Collections

    A set of query operators built into C# for filtering, transforming, and aggregating data (collections, and with the right provider, databases/XML) using a consistent, declarative syntax -- e.g. `users.Where(u => u.IsActive).Select(u => u.Name)` reads similarly to a database query but works directly over in-memory C# collections too.

    var activeNames = users.Where(u => u.IsActive).Select(u => u.Name).ToList();
  25. Are LINQ query operations like `.Where()` and `.Select()` executed immediately, or lazily?advancedNullable Reference Types, LINQ & Collections

    Lazily (deferred execution) -- the query is only actually evaluated when you enumerate its results (via a `foreach`, or calling `.ToList()`/`.ToArray()`), not at the point the LINQ expression is written -- this means the underlying data source could change between defining and actually enumerating the query, affecting the eventual result.

    Common mistake: Assuming a LINQ query executes immediately when written, rather than being lazily evaluated only once actually enumerated.

  26. What is the difference between `IEnumerable<T>` and `List<T>` in terms of what they guarantee?advancedNullable Reference Types, LINQ & Collections

    `IEnumerable<T>` only guarantees the ability to iterate over a sequence, potentially lazily/deferred and possibly only once; `List<T>` is a concrete, fully-realized, indexable, mutable collection -- calling `.ToList()` on an `IEnumerable<T>` forces immediate, full evaluation into a real in-memory list.

  27. What is the difference between `List<T>`, `Dictionary<TKey, TValue>`, and `HashSet<T>` as core .NET collection types?intermediateNullable Reference Types, LINQ & Collections

    `List<T>` is an ordered, resizable, index-accessible collection allowing duplicates; `Dictionary<TKey, TValue>` maps unique keys to values with fast lookup by key; `HashSet<T>` holds unique elements with fast membership testing but no meaningful positional order.

  28. What does `.FirstOrDefault()` return if no element in the sequence matches, and how does that differ from `.First()`?intermediateNullable Reference Types, LINQ & Collections

    `.First()` throws an exception if no matching element exists; `.FirstOrDefault()` returns the type's default value (`null` for reference types, `0` for `int`, etc.) instead of throwing -- choosing between them depends on whether 'no match' is an expected, normal case or a genuine error condition for that specific query.

  29. What is a common performance mistake when chaining multiple LINQ operations inside a loop?advancedNullable Reference Types, LINQ & Collections

    Re-executing a lazily-evaluated LINQ query multiple times (e.g. calling `.Count()` and then `.ToList()` separately on the same un-materialized query) re-runs the ENTIRE query pipeline each time -- materializing the result once (`.ToList()`) and reusing that concrete list avoids redundant recomputation.

  30. Why might overly long, deeply-chained LINQ expressions hurt readability compared to an equivalent explicit loop?advancedNullable Reference Types, LINQ & Collections

    A dense chain of `.Where().Select().GroupBy().OrderBy()` packs significant logic into one expression, which can become genuinely hard to read/debug once it grows complex -- LINQ is a readability WIN for straightforward filter/transform operations, but not an automatic win once the logic becomes intricate enough that a clearer imperative loop (or breaking the chain into named intermediate variables) would communicate intent better.

  31. What does the `async`/`await` pattern let you do in C#, and what does an `async` method typically return?intermediateAsync/Await & Exception Handling

    It lets you write asynchronous code (like an I/O-bound network call) that reads like sequential synchronous code -- an `async` method typically returns `Task` (no result value) or `Task<T>` (an eventual result of type `T`), representing the operation's eventual completion.

    public async Task<string> FetchDataAsync() {
      var response = await httpClient.GetStringAsync(url);
      return response;
    }
  32. Does `await` block the current thread while waiting for the awaited task to complete?advancedAsync/Await & Exception Handling

    No -- `await` releases the current thread back to do other work while the asynchronous operation is in progress, and execution resumes on (typically) a thread-pool thread once the awaited task completes -- this is precisely why `async`/`await` is valuable for scalable I/O-bound work, unlike a blocking synchronous wait.

  33. What is a common mistake when calling an async method without actually awaiting it?advancedAsync/Await & Exception Handling

    The async operation starts but the calling code continues immediately without waiting for it to complete or observing any exception it might throw -- an unhandled exception from a fire-and-forget async call can be silently lost, or surface much later and out of context, making the bug hard to trace back to its source.

    Common mistake: Calling an async method without awaiting it, letting any exception it throws go unobserved or surface later, disconnected from its actual cause.

  34. How do you run multiple independent async operations concurrently and wait for all of them to finish?advancedAsync/Await & Exception Handling

    `await Task.WhenAll(task1, task2, task3);` -- starts all the tasks and waits for every one to complete, running them concurrently rather than sequentially awaiting each one in turn (which would needlessly serialize otherwise-independent work).

  35. What is a try/catch/finally block used for, and what is guaranteed about the `finally` block?beginnerAsync/Await & Exception Handling

    `try` contains code that might throw; `catch` handles a specific (or general) exception type if one occurs; `finally` runs regardless of whether an exception occurred or was caught -- commonly used for guaranteed cleanup (closing a resource) that must happen either way.

  36. What does the `using` statement do in C#, and how does it relate to `IDisposable`?advancedAsync/Await & Exception Handling

    `using (var resource = ...) { ... }` guarantees `resource.Dispose()` is called automatically once the block exits, even if an exception is thrown -- works for any type implementing `IDisposable`, C#'s equivalent to a deterministic cleanup pattern for unmanaged resources like file handles or database connections.

    using (var file = new StreamReader(path)) {
      return file.ReadToEnd();
    }
  37. Why is catching a broad `Exception` type and doing nothing with it (an empty catch block) generally considered bad practice?intermediateAsync/Await & Exception Handling

    It silently discards information about a real failure, making the program appear to succeed when something actually went wrong -- the underlying problem surfaces later, in a confusing, disconnected way (or never surfaces at all), making the root cause far harder to diagnose than if the exception had been logged or handled meaningfully.

    Common mistake: Catching a broad Exception type with an empty catch block, silently swallowing a real failure instead of logging or handling it.

  38. What is the difference between checked and unchecked arithmetic overflow behavior in C#?advancedAsync/Await & Exception Handling

    By default (unchecked), an integer arithmetic overflow silently wraps around; wrapping the expression in a `checked` block causes it to throw an `OverflowException` instead -- useful when silent wraparound would be a serious, hard-to-detect bug in a specific calculation.

  39. What is a custom exception class in C#, and why might you define one rather than always throwing a generic `Exception`?advancedAsync/Await & Exception Handling

    A class deriving from `Exception` (e.g. `class InsufficientFundsException : Exception`) represents a specific, meaningful failure mode -- lets calling code catch and handle that SPECIFIC error type distinctly (`catch (InsufficientFundsException ex)`) rather than parsing a generic exception's message string to figure out what actually went wrong.

  40. Why should exceptions generally be reserved for genuinely exceptional conditions, not routine control flow (e.g. checking whether a key exists in a dictionary)?advancedAsync/Await & Exception Handling

    Throwing and catching exceptions has real runtime overhead compared to a normal conditional check, and using them for routine, expected outcomes (like a missing dictionary key, which `TryGetValue` handles cleanly without an exception) makes the code's control flow harder to follow -- exceptions communicate 'something unexpected happened,' not 'here's one of several normal outcomes.'

  41. What does `dotnet new console` do, and what files does it typically generate?beginner.NET Project Structure & the dotnet CLI

    It scaffolds a new console application project, generating a `.csproj` project file (describing the project's target framework and dependencies) and a starter `Program.cs` source file -- the standard starting point for a new .NET console project.

  42. What does the `.csproj` file define for a .NET project?intermediate.NET Project Structure & the dotnet CLI

    It's the project's manifest -- defining the target .NET framework version, package (NuGet) dependencies, and build-related settings -- roughly analogous in role to `package.json` in a Node.js project or `go.mod` in a Go project.

  43. What is the difference between `dotnet build` and `dotnet run`?beginner.NET Project Structure & the dotnet CLI

    `dotnet build` compiles the project into output binaries without executing it; `dotnet run` builds (if needed) AND immediately executes the resulting application -- `run` is typically used during active development, `build` alone when you just need the compiled output without running it.

  44. What does `dotnet test` do, and what testing frameworks does it commonly work with?intermediate.NET Project Structure & the dotnet CLI

    It discovers and runs a project's automated tests -- commonly used with frameworks like xUnit, NUnit, or MSTest, all of which integrate with the standard `dotnet test` command regardless of which specific testing framework a project has chosen.

  45. What is NuGet, and what role does it play in a .NET project?beginner.NET Project Structure & the dotnet CLI

    .NET's package manager -- it manages downloading, installing, and tracking versions of external library dependencies referenced in a project's `.csproj` file, similar in role to npm for Node.js or pip for Python.

  46. What does `dotnet publish` produce, and how does it differ from `dotnet build`?advanced.NET Project Structure & the dotnet CLI

    `dotnet publish` produces a self-contained, deployment-ready set of output files (optionally including the .NET runtime itself for a self-contained deployment) intended to actually be deployed to a server -- `dotnet build`'s output is meant more for local development iteration, not necessarily deployment-ready.

  47. What is the difference between a .NET SDK and the .NET runtime?advanced.NET Project Structure & the dotnet CLI

    The SDK includes everything needed to BUILD and develop .NET applications (compiler, CLI tools, project templates); the runtime alone is only what's needed to RUN an already-built .NET application -- a production server typically only needs the runtime installed, not the full SDK.

  48. What is a .NET solution file (`.sln`), and how does it relate to individual project files?advanced.NET Project Structure & the dotnet CLI

    A solution file groups multiple related `.csproj` projects together (e.g. a web API project plus its separate test project) so they can be opened, built, and managed together as one unit in an IDE or via the CLI -- a solution can reference several independently-buildable projects.

  49. Why might a .NET project pin exact NuGet package versions, similar to a lock file in other ecosystems?intermediate.NET Project Structure & the dotnet CLI

    Pinning exact versions ensures every environment installs the identical dependency code, avoiding a scenario where an unrelated upstream package update silently changes behavior between different developers' machines or between local development and CI/production.

  50. Why does .NET's cross-platform support (running on Windows, Linux, and macOS since .NET Core) matter for modern C# development, compared to the older, Windows-only .NET Framework?intermediate.NET Project Structure & the dotnet CLI

    It lets C#/.NET applications be developed and deployed on the same platforms as most other modern backend stacks (Linux containers, cloud environments) rather than being tied to Windows-only hosting -- a significant shift that broadened where and how .NET applications can realistically be deployed.