DEV Community

Cover image for One Clarifying Question, One Line of C#: 5 Interview Bugs I Planted on Purpose
MICHAEL-MAURICE
MICHAEL-MAURICE

Posted on

One Clarifying Question, One Line of C#: 5 Interview Bugs I Planted on Purpose

Most advice about coding interviews says "ask clarifying questions". It rarely says why the interviewer cares. My answer: every good clarifying question ends up as one specific line of code. If you can point at that line while you talk, you've shown you write code from requirements, not from memory.

To check that idea, I took a small practice project (four classic problems in C# on .NET 10, each with a brute force and an optimized version, 34 xUnit v3 tests) and broke one line at a time. Each line is the answer to a question you should ask out loud. Then I counted how many tests failed.

Four of the five bugs were caught. One got through all 34 tests, and that one taught me the most.

Tech Skill Builder is $5/month for a very limited time only (normally $10). Grab it now before it goes back to $10. Complete, working, tested .NET projects with full source code and step-by-step PDF guides: Tech Skill Builder.

If you're preparing for .NET backend interviews in general, my .NET Backend Interview Masterclass (2026 Edition) goes much wider than algorithms. More on it at the end.

How the experiment works

Every problem has one extra test besides the hand-picked cases: run the brute force and the optimized version on 500 random small inputs with a fixed seed, and require the same answer. The brute force is slow, but it's easy to trust, so it works as the reference for the fast one.

For each bug below I changed one line, ran dotnet test, wrote down what failed, and reverted the change.

Bug 1: "Can I use the same element twice?"

Two Sum, the hash map version. The answer "no" is enforced by the order of two lines: look up the complement first, insert the current value second.

for (var j = 0; j < nums.Count; j++)
{
    long complement = (long)target - nums[j];
    if (seen.TryGetValue(complement, out var i)) return (i, j); // 1. look up
    seen.TryAdd(nums[j], j);                                    // 2. then insert
}
// null check, doc comment and brute force: in the complete project
Enter fullscreen mode Exit fullscreen mode

What I broke: I moved the insert above the lookup.

What noticed: 3 tests. [3] with target 6 now "finds" a pair (index 0 with itself), [3, 3] returns (0, 0) instead of two different indices, and the random comparison failed too.

Say it out loud: "I check before I insert, so an element can't pair with itself."

Bug 2: "How big can the numbers get?" (the one that got through)

The same method does its math in long, because int.MaxValue + 1 silently wraps around in an int. The project even has a test row for it: [int.MaxValue, 1, int.MinValue] with target -1.

What I broke: I switched both the brute force and the optimized version to plain int arithmetic.

What noticed: nothing. 34 of 34 passed.

The reason is a little embarrassing. In that test row, the correct pair (int.MaxValue + int.MinValue = -1) doesn't overflow at all, so int math still finds it. The row looks like overflow coverage, but it can't fail. And the random test couldn't help: it uses small values, and I had broken both versions in the same way, so they still agreed.

The case that does catch it is one where wrapping creates a false match:

{ [int.MaxValue, 1], int.MinValue, false }, // int math: MaxValue + 1 wraps to MinValue
Enter fullscreen mode Exit fullscreen mode

I added that row in a scratch copy, and the int version failed it straight away (the real long version passes). It isn't in the project yet.

Say it out loud: "If the values can be near int.MaxValue, I'll add in long. And my test for that needs a case where wrapping would produce a wrong yes, not just one where it happens to work."

Bug 3: "What if the repeat is already outside my window?"

Longest substring without repeating characters, sliding window version. This one isn't a question for the interviewer. It's a question you ask yourself while you trace an example.

if (lastIndex.TryGetValue(s[right], out var previous))
    left = Math.Max(left, previous + 1); // the left edge never moves backwards
// rest of the loop (update lastIndex, track best): in the complete project
Enter fullscreen mode Exit fullscreen mode

What I broke: left = previous + 1; without the Math.Max.

What noticed: 2 tests: the "abba" row (the broken version returns 3, the right answer is 2) and the random comparison.

Say it out loud: "Let me trace abba. At the last a, the previous a is at index 0, which is already outside the window, so left must stay where it is."

Bug 4: "Must the subarray be non-empty?"

Maximum subarray (Kadane). If the answer is "yes, take at least one element", then an all-negative array returns its largest single value, not 0. That decision lives in the seed:

long endingHere = nums[0], best = nums[0]; // not 0
// the loop and the empty-input guard: in the complete project
Enter fullscreen mode Exit fullscreen mode

What I broke: seeded both with 0.

What noticed: 2 tests: [-3, -1, -2] (expected -1) and the random comparison.

Say it out loud: "You said non-empty, so I seed with the first element. Otherwise an all-negative input would return 0, which isn't the sum of any subarray."

Bug 5: "If one meeting ends at 10 and the next starts at 10, can they share a room?"

Meeting rooms, sort-and-sweep version. If the end time is exclusive, a room is freed when the next start is at or after the earliest end. That's one character:

while (e < ends.Length && ends[e] <= start) { e++; rooms--; }
// sorting starts and ends, and counting rooms: in the complete project
Enter fullscreen mode Exit fullscreen mode

What I broke: <= to <.

What noticed: 2 tests: back-to-back meetings 9-10, 10-11, 11-12 (expected 1 room) and the random comparison.

Say it out loud: "That <= is your answer from earlier. Back-to-back meetings can share a room."

What the scoreboard says

Bug Clarifying question Tests that failed
Insert before lookup Same element twice? 3
int instead of long How big are the values? 0
No Math.Max on left Repeat outside the window? 2
Kadane seeded with 0 Non-empty subarray? 2
< instead of <= Exclusive end time? 2

Two things I took from it:

  1. The random brute-force comparison was in every catch. It failed on its own for all four bugs that were caught. In an interview you won't have time to write it, but one sentence earns credit: "With more time, I'd check this against the brute force on random small inputs."
  2. A test named after an edge case isn't proof that the edge case is covered. The overflow row looked right and couldn't fail. Breaking the line on purpose is the quickest way to find out.

Your practice checklist

  • [ ] Ask the question, then write the answer as a comment or a test case
  • [ ] Point at the line that implements each answer
  • [ ] Trace one awkward input by hand (abba, all negative, back-to-back)
  • [ ] For overflow, test a case where wrapping gives a false yes
  • [ ] Mention the brute-force cross-check, even if you can't write it

Want to go further?

The .NET Backend Interview Masterclass (2026 Edition) is a 142-page guide ($20) with 200+ C# questions with full code, a system design playbook with 7 high-frequency scenarios (webhooks, payments, feed pagination and more) and a 6-box thinking script, EF Core and SQL performance, the ASP.NET Core runtime, security and reliability, a 14-day prep plan, a STAR+L behavioral bank and 8 printable cheat sheets. To be upfront: the small kata project from this post is my own and isn't part of the guide.

And if you learn best from complete code you can run, Tech Skill Builder gives you complete, working, tested .NET projects with full source code and step-by-step PDF guides, with new ones added regularly. Tech Skill Builder is $5/month for a very limited time only (normally $10). Grab it now before it goes back to $10. Join Tech Skill Builder

Which clarifying question has saved you in a real interview?

Top comments (0)