C# Advanced - Topic-wise Practice
15 hard problems. Predict output, spot bugs, write code. No multiple choice.
1. Delegates & Events - 3 Problems
P1. Predict Output: What prints?
Action a = null;
a += () => Console.Write("A");
a += () => Console.Write("B");
a -= () => Console.Write("A");
a?.Invoke();
Show Solution
ABWhy:
-= only removes if delegate instance matches. Lambdas create new instances. The -= did nothing. Both A and B remain. Use named methods to remove: a -= MyMethod;
P2. Spot the Bug: Memory leak. Find it.
class Window {
public Window(Button btn) {
btn.Click += () => this.Close(); // Prerna's code
}
}
Show Solution
this. Button now holds ref to Window. If Button lives longer than Window, Window never GC'd. Fix: Unsubscribe in Dispose, or use named method +
-=, or WeakEventManager.
P3. Write Code: Create SafeEvent<T> that won't throw if null and catches subscriber exceptions.
Show Solution
public class SafeEvent<T> {
private event Action<T> _handlers;
public void Subscribe(Action<T> handler) => _handlers += handler;
public void Unsubscribe(Action<T> handler) => _handlers -= handler;
public void Raise(T args) {
var handlers = _handlers; // Thread-safe copy
if (handlers == null) return;
foreach (Action<T> handler in handlers.GetInvocationList()) {
try { handler(args); }
catch (Exception ex) { Console.WriteLine($"Handler failed: {ex}"); }
}
}
}
2. LINQ - 3 Problems
P4. Predict Output: How many times does "Check" print?
var nums = new List<int> {1,2,3};
var q = nums.Where(n => { Console.WriteLine("Check"); return n > 1; });
Console.WriteLine(q.Count());
Console.WriteLine(q.Count());
Show Solution
Why: Deferred execution.
q.Count() enumerates q each time. 3 items ร 2 calls = 6 checks. Fix: var list = q.ToList(); materialize once.
P5. Spot the Bug: This is slow. Why?
var result = db.Users
.Where(u => u.IsActive)
.ToList()
.Where(u => u.Orders.Any(o => o.Total > 100)) // Kaushal's filter
.ToList();
Show Solution
ToList() loads ALL active users to memory. Then filters in C#, not SQL. If 1M users, you pull 1M rows.Fix: Remove first
ToList(). Let EF translate whole query to SQL: db.Users.Where(u => u.IsActive && u.Orders.Any(...)).ToList()
P6. Write Code: Given List<string> names, return dictionary of first-letter โ count, using LINQ.
Show Solution
var counts = names
.GroupBy(n => n[0])
.ToDictionary(g => g.Key, g => g.Count());
// Result: { 'K': 3, 'P': 2 } for ["Kunal", "Kaushal", "Karan", "Prerna", "Prerna"]
3. Async & Await - 3 Problems
P7. Predict Output: Order?
async Task Test() {
Console.Write("A");
await Task.Delay(1);
Console.Write("B");
}
Console.Write("C");
Test();
Console.Write("D");
Show Solution
CADBWhy: C prints. Test() prints A, hits await, returns to caller. D prints. Later B prints when Delay completes.
P8. Spot the Bug: Sanju's API is slow. Why?
public async Task<User> GetUser(int id) {
var user = await db.Users.FindAsync(id);
var orders = await db.Orders.Where(o => o.UserId == id).ToListAsync();
var posts = await db.Posts.Where(p => p.UserId == id).ToListAsync();
return user;
}
Show Solution
Fix: Start all, then await all:
var t1 = db.Users.FindAsync(id); var t2 =...; await Task.WhenAll(t1,t2,t3); Now ~100ms total.
P9. Write Code: Implement Task.Delay using TaskCompletionSource.
Show Solution
public static Task Delay(int ms) {
var tcs = new TaskCompletionSource<bool>();
var timer = new System.Timers.Timer(ms) { AutoReset = false };
timer.Elapsed += (s, e) => { tcs.SetResult(true); timer.Dispose(); };
timer.Start();
return tcs.Task;
}
4. Generics - 3 Problems
P10. Predict Output: What prints?
void Print<T>(T item) => Console.Write(typeof(T).Name);
Print(5);
Print("hi");
Show Solution
Int32StringWhy: Compiler infers T from argument. T = int, then T = string.
typeof(T).Name gives type name.
P11. Spot the Bug: Why won't this compile?
class Cache<T> {
T value;
public bool IsNull() => value == null; // Karan's code
}
Show Solution
int, value == null is invalid. int can't be null.Fix:
where T : class constraint, or use EqualityComparer<T>.Default.Equals(value, default(T))
P12. Write Code: Generic Swap<T>(ref T a, ref T b)
Show Solution
public static void Swap<T>(ref T a, ref T b) {
T temp = a;
a = b;
b = temp;
}
// Usage: int x=1,y=2; Swap(ref x, ref y);
5. File I/O - 3 Problems
P13. Predict Output: File has "AB\nCD". What prints?
using var r = new StreamReader("f.txt");
Console.Write(r.ReadLine());
Console.Write(r.ReadToEnd());
Show Solution
ABCDWhy:
ReadLine() reads "AB" and consumes \n. ReadToEnd() reads "CD". No newline printed between.
P14. Spot the Bug: "File in use" error. Why?
var w = new StreamWriter("log.txt");
w.WriteLine("Start");
//... crash here
w.WriteLine("End"); // Kashvee never reaches this
Show Solution
using or Dispose(). If exception occurs, file handle never released. File stays locked.Fix:
using var w = new StreamWriter("log.txt"); Dispose called even on exception.
P15. Write Code: Async method to count lines in 10GB file without loading to RAM.
Show Solution
public static async Task<long> CountLinesAsync(string path) {
long count = 0;
using var reader = new StreamReader(path);
while (await reader.ReadLineAsync()!= null) {
count++;
}
return count;
} // Memory: 4KB buffer. Works for any file size.
No comments yet. Be the first to share your thoughts!