C# Interview Questions & Answers
30 most asked questions for 0-3 year roles. Ordered by difficulty: Fresher โ Junior โ Mid-level.
Fresher Level: Core Syntax
Answer: C# is a modern, type-safe, object-oriented language by Microsoft. It's compiled to IL (Intermediate Language) by the C# compiler, then JIT-compiled to native machine code by CLR at runtime. So hybrid: compiled to IL, then JIT/interpreted.
Follow-up: What is CLR? Common Language Runtime - manages memory, GC, security, JIT.
Follow-up: What is CLR? Common Language Runtime - manages memory, GC, security, JIT.
Answer: No difference.
int is C# keyword alias for.NET type System.Int32. Same for string/String, bool/Boolean. Use lowercase aliases in C# code by convention.
Answer:
double uses binary floating-point. 0.1 + 0.2 = 0.30000000000000004 due to base-2 rounding. decimal uses base-10, so 0.1m + 0.2m = 0.3m exactly. decimal has 28-29 digit precision. Critical for financial calculations. double is faster but inaccurate.
Answer:
Use when: Type is obvious:
Don't use when: Type unclear:
var = implicit typing. Compiler infers type from right side. var x = 5; โ int x = 5;Use when: Type is obvious:
var list = new List<int>();Don't use when: Type unclear:
var data = GetData(); What is data? Hurts readability.
Answer: Array: Fixed size
List<T>: Dynamic size
int[] arr = new int[3];. Faster access, less memory overhead. Cannot resize.List<T>: Dynamic size
List<int> list = new(); list.Add(5);. Resizes automatically. Slight overhead. Use List 99% unless performance critical with known size.
Answer: Thrown when you access member of null reference.
Avoid: 1. Check
string s = null; int len = s.Length; โ crash.Avoid: 1. Check
if(s!= null) 2. Null-conditional s?.Length 3. Null-coalescing s?? "default"
Answer: For strings, both compare values due to operator overloading.
"hi" == "hi" true. For reference types, == compares references by default, Equals() compares values if overridden.
Answer:
Instance method:
static belongs to type, not instance. Call without new. Example: Math.Sqrt(4), int.Parse("5"), Console.WriteLine().Instance method:
List<int> list = new(); list.Add(5); needs object. Use static for utilities that don't need object state.
for: Known iterations.
foreach: Iterate collections.
while: Unknown iterations.
do-while: Runs at least once. Check after loop.
for(int i=0; i<10; i++)foreach: Iterate collections.
foreach(var item in list). No index, can't modify collection.while: Unknown iterations.
while(!done). Check before loop.do-while: Runs at least once. Check after loop.
break: Exit loop immediately.
continue: Skip current iteration, go to next.
for(...){ if(x==5) break; } stops at x=5.continue: Skip current iteration, go to next.
for(int i=0;i<5;i++){ if(i==2) continue; } skips 2, prints 0,1,3,4.
Junior Level: Methods & Exceptions
Answer: Both pass by reference, so method can modify caller's variable.
ref: Variable MUST be initialized before call. Method can read/write.
out: No init needed. Method MUST assign before return.
Use
ref: Variable MUST be initialized before call. Method can read/write.
int x=5; Method(ref x);out: No init needed. Method MUST assign before return.
int.TryParse("123", out int x);Use
out for multiple return values. Use ref for two-way.
Boxing: Value type โ reference type.
Unboxing: reference โ value.
Impact: Avoid in hot paths.
int i = 5; object o = i; Allocates heap, copies value. Slow.Unboxing: reference โ value.
int j = (int)o; Cast required, throws if wrong type.Impact: Avoid in hot paths.
List<int> uses generics, no boxing. ArrayList boxes everything.
Answer: try โ if exception, catch โ finally always runs. Even if
Use:
return in try/catch, finally executes before method returns.Use:
finally for cleanup: close files, dispose connections, release locks. using statement is syntax sugar for try-finally-Dispose.
String: Immutable.
StringBuilder: Mutable.
Rule: Use StringBuilder for >5 concatenations or loops. String for 2-3 concats is fine.
s += "a"; creates new string object. In loop of 1000, creates 1000 objects. GC pressure.StringBuilder: Mutable.
sb.Append("a"); modifies internal buffer. No new objects until capacity exceeded.Rule: Use StringBuilder for >5 concatenations or loops. String for 2-3 concats is fine.
Answer: Language Integrated Query. Query objects, DB, XML with SQL-like syntax.
Method syntax:
Query syntax:
Common: Where, Select, OrderBy, GroupBy, Sum, Any, First, Single.
Method syntax:
var evens = numbers.Where(n => n % 2 == 0).ToList();Query syntax:
var evens = from n in numbers where n % 2 == 0 select n;Common: Where, Select, OrderBy, GroupBy, Sum, Any, First, Single.
Field:
Property:
Auto-property:
public int age; Direct access. No validation. Breaks encapsulation.Property:
public int Age { get; set; } Controls access. Can add logic: get => _age; set => _age = value >= 0? value : 0;Auto-property:
public int Age { get; set; } Compiler creates backing field. Use 90% of time.
Answer: Multiple methods same name, different parameters. Compiler picks based on args.
Cannot overload by return type only. Must differ in parameter type/count/order.
int Add(int a, int b) vs double Add(double a, double b) vs int Add(int a, int b, int c)Cannot overload by return type only. Must differ in parameter type/count/order.
Answer:
Rules: 1. Must be last parameters 2. Must have compile-time constant default 3. Call with named args to skip:
Cannot:
void Log(string msg, bool urgent = false)Rules: 1. Must be last parameters 2. Must have compile-time constant default 3. Call with named args to skip:
Log("hi", urgent: true)Cannot:
(int x = 0, string y) Error. Optional must be after required.
Answer: Shorthand using
Method:
Property:
Constructor:
Read-only properties, methods with single return only.
=> for single-expression members.Method:
int Square(int x) => x * x; vs { return x * x; }Property:
public int Age => _birthYear - DateTime.Now.Year;Constructor:
public Person(string n) => Name = n;Read-only properties, methods with single return only.
Answer:
Rule: Always use
throw; rethrows same exception, preserves stack trace. throw ex; resets stack trace to current line, loses original error location.Rule: Always use
throw; in catch to rethrow. Use throw new Exception() to throw new one.
Mid-Level: Deeper Concepts
init:
readonly field:
Diff:
public string Name { get; init; } Can set only during object initialization: new Person { Name = "A" }; After that, read-only. For immutable objects.readonly field:
readonly int id; Can set only in constructor or field initializer. Not in property setter.Diff:
init allows object initializer syntax. readonly requires constructor param.
IEnumerable: In-memory. LINQ to Objects.
IQueryable: Builds expression tree. LINQ to SQL/EF.
Rule: Use IQueryable for DB queries to avoid loading millions of rows. Use IEnumerable for in-memory collections.
list.Where() runs in C# after loading all data.IQueryable: Builds expression tree. LINQ to SQL/EF.
db.Users.Where() converts to SQL, runs in DB.Rule: Use IQueryable for DB queries to avoid loading millions of rows. Use IEnumerable for in-memory collections.
Answer: Ensures
C# 8+:
Dispose() called even if exception. Syntax sugar for try-finally.using (var file = File.OpenRead("a.txt")) {... } โก var file = File.OpenRead(); try {... } finally { file?.Dispose(); }C# 8+:
using var file = File.OpenRead(); Disposes at end of scope. For: File, DB connection, HttpClient.
Value: Stored on stack. Copy by value.
Reference: Stored on heap. Copy reference.
Key:
int, double, bool, struct, enum. int a=5; int b=a; b=10; a still 5.Reference: Stored on heap. Copy reference.
string, class, array, delegate. int[] a={1}; int[] b=a; b[0]=10; a[0] also 10.Key:
string is reference but immutable, so behaves like value.
Delegate: Type-safe function pointer.
Action: Built-in delegate, returns void.
Func: Returns value.
Use: Callbacks, LINQ, events.
delegate int Calc(int a, int b);Action: Built-in delegate, returns void.
Action<string> log = Console.WriteLine;Func: Returns value.
Func<int,int,int> add = (a,b) => a+b; Last type is return.Use: Callbacks, LINQ, events.
list.Where(x => x > 5) uses Func<int,bool>.
const: Compile-time constant.
readonly: Runtime constant.
static readonly: One per type.
Rule: Use const for true constants like Pi. readonly for config set once.
const int Max = 100; Implicitly static. Must be literal. Embedded in IL.readonly: Runtime constant.
readonly int id; Set in constructor only. Instance or static.static readonly: One per type.
static readonly DateTime Start = DateTime.Now; Can use runtime values.Rule: Use const for true constants like Pi. readonly for config set once.
Answer: Async programming without blocking threads.
Why: UI stays responsive. Web server handles 1000s of requests with few threads. Without await, thread blocks.
Rule: async all the way. Don't use
async Task<string> GetData()await http.GetStringAsync(url); Releases thread while waiting. Thread returns to pool.Why: UI stays responsive. Web server handles 1000s of requests with few threads. Without await, thread blocks.
Rule: async all the way. Don't use
.Result or .Wait() - causes deadlocks.
First(): Returns first element. Throws if empty.
FirstOrDefault(): Returns first or default(T) if empty. No exception.
Single(): Expects exactly 1. Throws if 0 or >1. Use to enforce uniqueness.
SingleOrDefault(): 0 or 1 OK. Throws if >1.
Rule: Use OrDefault for optional. Use Single when DB should have exactly 1.
FirstOrDefault(): Returns first or default(T) if empty. No exception.
Single(): Expects exactly 1. Throws if 0 or >1. Use to enforce uniqueness.
SingleOrDefault(): 0 or 1 OK. Throws if >1.
Rule: Use OrDefault for optional. Use Single when DB should have exactly 1.
Answer: CLR automatically frees memory for unreferenced objects.
Gen 0: New objects. Collected frequently. Fast.
Gen 1: Survived Gen 0. Buffer between short/long lived.
Gen 2: Long-lived objects. Collected rarely. Expensive.
LOH: Large Object Heap >85KB. Collected with Gen 2.
Tip: Avoid LOH by pooling arrays. Gen 0 allocations are cheap.
Gen 0: New objects. Collected frequently. Fast.
Gen 1: Survived Gen 0. Buffer between short/long lived.
Gen 2: Long-lived objects. Collected rarely. Expensive.
LOH: Large Object Heap >85KB. Collected with Gen 2.
Tip: Avoid LOH by pooling arrays. Gen 0 allocations are cheap.
record: C# 9+. Reference type with value semantics. Auto
class: Reference semantics.
Use record for: DTOs, API models, data transfer. Use class for entities with identity/behavior.
with expression:
Equals, GetHashCode, ToString. Immutable by default: record Person(string Name);class: Reference semantics.
== compares references. Must override Equals manually.Use record for: DTOs, API models, data transfer. Use class for entities with identity/behavior.
with expression:
var p2 = p1 with { Name = "B" }; Non-destructive mutation.
Interview Pro Tip: Don't just memorize. For every question, give 1-line answer + 1 code example + 1 "why it matters". Example: "Use
decimal for money because double has binary rounding errors. 0.1+0.2โ 0.3 breaks financial calcs."
No comments yet. Be the first to share your thoughts!