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.

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: 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 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. 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: 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. 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. 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. 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. 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 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. 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: 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: 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.
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: 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 => 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: 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: 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. 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 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. 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. 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. 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. 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.

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.

record: C# 9+. Reference type with value semantics. Auto 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."

Comments on Interview Questions (0)

No comments yet. Be the first to share your thoughts!