Last updated: November 11, 2026
By Robert Ardell, Co-Founder and Strategic Advisor, KORE1
Good C# developer interview questions in 2026 hand a candidate twelve lines of code and ask what breaks, instead of asking for a definition. Plenty of people can recite value types versus reference types, and far fewer can explain why a singleton that holds a DbContext falls over on the busiest day of the quarter.
A property insurer in Omaha learned that in October. Their homeowner rating service quoted a policy in about forty milliseconds on a normal day, but the Monday after a hailstorm quote volume roughly tripled and the service began returning prices that were off by a few dollars, and off differently each time anyone refreshed the page. Intermittent errors showed up in the logs as well, something about a second operation starting before the first one had finished, and nobody on the team had seen that message before.
The developer who wrote the rate cache had interviewed well. He handled abstract class versus interface, boxing, and delegates without hesitating, and nobody had asked him what lifetime a DbContext has, so he registered the cache as a singleton that took the context in its constructor. That put one database connection object in the hands of every request thread the server could muster. It had worked for eight months because traffic never overlapped enough to matter.
Here’s the detail that still bugs me. ASP.NET Core would have refused to start that app. Scope validation catches exactly this mistake, but it only switches on by default when the environment is Development, and the team’s docker-compose file had been copied from the deploy config with the environment set to Production, so every laptop they owned had the check turned off. A contractor we placed found the problem in an afternoon, swapped in a context factory, and went home.

What follows is the question set I’d hand a panel hiring through our C# developer staffing desk, and it skips ground we’ve covered elsewhere on purpose. Pay bands and the job description mistakes that stall searches live in the guide to hiring C# and .NET developers, and the question of whether you’re running a .NET platform search or a language search is sorted on our .NET developer staffing page. This page is only the interview.
I should say where I sit. KORE1 collects a fee when you hire through us, and pages like this one are how a lot of hiring managers decide whether to call, so weigh what follows accordingly. Every question below works fine without us.
What a C# Interview Has to Prove
A C# developer interview should show that a candidate can predict what a piece of code does at runtime, not just name the feature it uses. Definitions are cheap and easy to rehearse, while prediction with a plausible bug sitting in plain view is much harder to fake.
The language is not a niche bet, which is part of why the loop matters so much. C# ranked eighth in the Stack Overflow 2026 Developer Survey, used by 27.1% of respondents. Federal pay data doesn’t break out C# separately, so the nearest proxy is software developers, where the Bureau of Labor Statistics reports a May 2025 median of $135,980 across about 1.69 million jobs, with the 10th percentile at $82,460 and the 90th at $214,670. Two people with “C#, six years” on the resume can sit at opposite ends of that spread.
We run these searches for a living, and KORE1 averages 17 days to hire on IT roles while our placements hold at 92% through twelve months, which gives us a decent view of what a loop gets wrong. In C# the early exits we see trace back to a loop that graded vocabulary and never tested whether the person could read a service and say where it would fall over.
The language also moved. C# 14 shipped with .NET 10 in November 2025, and .NET 10 is a long-term support release, so it’s where teams are heading as .NET 8 and 9 reach the end of support on November 10, 2026 (the retarget planning piece covers who does that work). A loop written in 2021 asks about things the compiler now does for you.
| Release | What changed | The question it earns |
|---|---|---|
| C# 12 / .NET 8 | Primary constructors on any class or struct; collection expressions; the TimeProvider class | “The constructor parameter is in scope for the whole class. What does that do to a field you meant to be read-only?” |
| C# 13 / .NET 9 | System.Threading.Lock type; params accepts spans and collections; partial properties | “What does the lock statement do differently when the target is the new Lock type?” |
| C# 14 / .NET 10 | The field keyword in property accessors; extension members; null-conditional assignment | “Rewrite this validating setter without declaring a backing field. What breaks if the class already has a member named field?” |
Round One, Read the Code
When we run this round, the snippet goes on a shared screen and I ask what happens, then what the candidate would change, then how the team could have caught it before it shipped. The third question is where seniority shows up. Each snippet gets six to eight minutes, and nobody gets to run it.
“This app starts. Does it work?”
builder.Services.AddDbContext<RatesDb>();
builder.Services.AddSingleton<RateCache>();
public class RateCache(RatesDb db)
{
public Task<List<Rate>> LoadAsync() => db.Rates.ToListAsync();
}That’s the Omaha bug, trimmed. AddDbContext registers the context as scoped, and a singleton that takes a scoped service is what Microsoft’s dependency injection guidelines call a captive dependency. With scope validation on, you get an InvalidOperationException saying it cannot consume a scoped service from a singleton, and with validation off you get one context for the life of the process.
A strong candidate says that before I’ve finished scrolling, then adds the part that matters. EF Core’s documentation is blunt that a DbContext is not thread-safe, so under load the failure shows up as the second-operation error plus stale tracked entities that never refresh, and the fix is a context factory, or an IServiceScopeFactory and a fresh scope for each refresh.
The third question gets the real signal, and it’s the one most panels never ask. Why did this ever reach production? The answer I’m listening for involves the environment name, because the framework only turns scope validation on in Development by default, and staff-level people go one step further and propose turning ValidateScopes and ValidateOnBuild on everywhere, including the build server.
“The endpoint returns 202. What happens to the receipt?”
app.MapPost("/orders", async (Order order, OrdersDb db) =>
{
db.Orders.Add(order);
await db.SaveChangesAsync();
_ = Task.Run(() => SendReceiptAsync(order, db));
return Results.Accepted();
});The receipt method uses the same scoped context, and the request’s scope is disposed once the response goes out. Whether the background task finishes before that happens is a race, and in a developer’s debugger it usually wins, while under production load it usually loses and the exception lands in a task nobody awaits. The customer just never gets the email.
Plenty of candidates find the disposed context. Fewer say what they’d do instead, which is hand the work to a queue (a Channel and a BackgroundService is the stock answer) and open a new scope inside the worker, and fewer still ask whether a lost receipt is acceptable at all, because in some businesses that’s a shrug and in others it’s a compliance problem.
“Why didn’t the update stick?”
var list = new List<Point> { new Point { X = 1 } }; // Point is a struct
var p = list[0];
p.X = 5;
Console.WriteLine(list[0].X);It prints 1. The indexer returned a copy of the struct, the assignment changed the copy, and the list never heard about it. I like this one because it separates people who’ve been burned by value semantics from people who’ve only read about them, a gap you can’t see on a resume and can hear within about four seconds. Better answers mention that the compiler refuses to let you write list[0].X = 5 directly, and the best ones add that mutable structs are mostly a mistake and offer a record struct or a readonly struct instead.
“Why is the invoice a cent off from the vendor’s?”
decimal a = 2.5m, b = 3.5m;
Console.WriteLine(Math.Round(a)); // 2
Console.WriteLine(Math.Round(b)); // 4Math.Round on a decimal defaults to rounding midpoints to the nearest even number, which people call banker’s rounding. A billing team in Raleigh spent two weeks reconciling a few thousand invoice lines because their old system had rounded half up and the rewrite never said so, and the whole month’s difference came to under forty dollars. It was still an audit finding.
Money belongs in every C# loop that touches billing, payroll, or pricing, and so do floating point and rounding mode. A good candidate reaches for decimal without being prompted and asks which rounding rule the business actually specifies before writing a line.

Round Two, The Part Most Lists Skip
Search this topic and the first page is mostly beginner material, namespaces and method overloading and which keyword stops inheritance, and little of it touches C# 12 through 14. That matters because the newer features change which mistakes are possible, and a candidate who stopped learning in 2020 will write 2020 code on your .NET 10 project without noticing.
“Rewrite this setter without a backing field.”
public string Name
{
get;
set => field = value ?? throw new ArgumentNullException(nameof(value));
}The field keyword is the compiler-generated backing store, new in C# 14 per Microsoft’s release notes. Strong candidates know it, and better ones know the catch, which is that a class with an existing member named field now reads ambiguously and you disambiguate with @field or this.field. If they’ve never seen the syntax, that’s fine and it’s information. If they’ve seen it and can’t name the catch, they read a blog post.
“What does this line do when customer is null?”
customer?.Discount = CalculateDiscount();Nothing happens, and CalculateDiscount is never called, since C# 14 evaluates the right side of a null-conditional assignment only when the receiver isn’t null. My follow-up is where that silence hurts. A discount that quietly fails to apply turns into a customer complaint, so sometimes the explicit null check is the better code.
Nullable reference types have been on by default in new project templates since .NET 6, so I also ask when the null-forgiving operator is honest and when it’s a lie told to the compiler. There’s no single right answer there, and I’m listening for reasoning.
Round Three, What Runs in Production
These need no screen. We ask them out loud on phone screens because the answers carry scar tissue, or they don’t, and you can hear which within a minute.
“Is it fine to create an HttpClient inside the method and dispose it?”
No, and the opposite habit is also wrong, which is what makes it a good question. Microsoft’s HttpClient guidelines explain that a new client per request can exhaust the operating system’s ports, since closed TCP connections linger in TIME-WAIT, while a single static client avoids that but never re-resolves DNS, so a service behind a changing address gets stuck. The documented answers are a long-lived client with PooledConnectionLifetime set, or short-lived clients from IHttpClientFactory.
On a screen last quarter, a senior candidate for a billing-platform contract in Tulsa said he used the factory everywhere, which is a fine answer. Then we asked what happens to cookies. He paused for a few seconds, then said the handlers get pooled, so the cookie container ends up shared between unrelated callers, and that he’d never route a cookie-dependent call through it, which is exactly what the guidelines say. We submitted him that afternoon.
Seven that sort people in two minutes
- Waiting for a lock without blocking a thread. You can’t await inside a lock statement, so the answer is SemaphoreSlim and WaitAsync, and the weak answer is wrapping the whole method in Task.Run.
- An IQueryable passed to a method that declares the parameter as IEnumerable of Order, followed by a Where call. The filter runs in memory after the whole table is pulled, and the fix is one parameter type.
- Throw versus throw ex inside a catch block. One keeps the original stack trace, the other resets it to the line you just wrote, and the on-call engineer finds out at three in the morning.
- A static Dictionary used as a cache in a web app. Microsoft documents the type as safe for several readers only while nobody modifies it, so what happens when two requests write at the same moment, and what would they use instead?
- Your overdue-invoice test only fails on the first of the month. What would you inject so a test can set the clock? The expected answer is TimeProvider, added in .NET 8, with FakeTimeProvider from the Microsoft.Extensions.TimeProvider.Testing package in the test project.
- Why doesn’t a method with yield return throw when you call it with a null argument? Deferred execution, so validation inside an iterator waits until somebody enumerates it.
- Two variables typed as object hold equal strings that were built separately. Does == say they match? No, it compares references, and Equals would say yes. It rarely comes up, and when it does it’s expensive.
When the Role Isn’t a Web API
Most C# question lists assume ASP.NET Core, and a good share of the C# roles we fill aren’t that. A Unity studio, a medical device team with a WPF front end, and a trading desk all hire people who write the same language and would fail each other’s loops.
For desktop work I ask what happens when a button click runs a three-second database call on the UI thread. The window freezes, which everyone knows, and the right answer is an awaited call that hands control back to the message loop rather than a Task.Run wrapped around a blocking one. A candidate who has shipped WPF will add that touching a control from a background thread throws unless the work goes back through the dispatcher, a detail that tends to arrive with a story about a plant-floor screen.
For Unity, I ask where garbage comes from inside a per-frame loop. LINQ, string concatenation, boxing, and closures all allocate, and an allocation every frame becomes a collection pause every few seconds.
For low-latency systems I ask how they’d parse a message without allocating. Span of T, a pooled buffer, a struct instead of a class. If they start talking about the garbage collector’s generations instead, they’re describing the problem and haven’t solved it.
Scoring the Answers
Grade the reasoning, not the recitation. A candidate who lands on the right answer for the wrong reason has memorized a list, while a candidate who gets it half wrong but says “I’d want to check the environment name first” is someone you can work with, because that sentence is the job.
| Level | Should say without prompting | Red flag |
|---|---|---|
| Mid-level, 3 to 5 years | Spots the shared context or the copied struct. Names the fix. | Defines terms and stops. Can’t predict the output. |
| Senior, 6 to 10 years | Names the mechanism, the symptom under load, and why dev never showed it. | Offers a fix with no explanation of why it fails. |
| Staff or architect | Asks how the team would have caught it before merge, and proposes a check. | “I’d just review more carefully.” |
Inside an hour, the loop we suggest runs roughly like this.
- Ten minutes on something they shipped, ending with what they’d change.
- Twenty-five minutes on two snippets from Round One, with the third follow-up asked every time.
- Ten on one modern C# question from Round Two, skipped if the codebase is still on .NET Framework.
- Ten on the production questions, out loud.
- Five for their questions, where what they ask about your deployment pipeline tells you more than what they ask about perks.
A few older questions can go. Abstract class versus interface and the garbage collector’s three generations are fine as warm-ups, but they’re the questions every candidate has prepared, and if one takes more than ninety seconds the interview is heading the wrong way.
The four kinds of C# search also need different panels. Unity candidates get allocation questions, desktop candidates get UI thread questions, and low-latency candidates get struct layout and pause questions. Our game developer interview questions cover the frame budget round if the role leans that way.

Questions Panels Ask Us
How many questions fit in one C# interview?
Six to eight, if each one gets a real follow-up. A panel that races through twenty definitions in an hour learns less than one that spends ten minutes on a single piece of broken code.
Do we still ask about value types versus reference types?
Only as a warm-up, never as the main event. Make it the setup for a snippet like the struct copy above, so the candidate has to apply the idea instead of reciting it. If someone answers the definition perfectly and then misses the snippet, you’ve learned what you needed.
Live coding or a take-home for a C# role?
Live reading beats both. Show code, ask what breaks, and keep it under an hour. Take-homes now arrive polished by an assistant, so the useful skill is explaining and defending code, which only a conversation tests.
What separates a mid-level C# developer from a senior one in an interview?
Where the answer starts. Mid-level candidates describe what the code does, while senior candidates start with what fails and when, and they ask about the environment before proposing a fix. That habit is hard to fake for forty-five minutes.
Can a .NET Framework veteran handle a .NET 10 role?
Often, with a ramp. The language carries over, but the runtime, the hosting model, and the dependency injection defaults do not. Test for willingness and speed on the newer ideas, then check the migration picture in our .NET 8 end-of-life plan before you decide what the role needs.
What does a C# developer cost in 2026?
$115K to $145K for mid-level and $150K to $200K for senior, according to our hiring guide, with contract rates of $70 to $95 an hour at mid-level and $100 to $140 at senior. Check a specific band with the salary benchmark assistant, and see our C# developer salary guide for why the public salary pages disagree. Domain and metro move the number more than the year count does.
Run It Once Before You Use It
Give the snippets to your own best C# engineer first. If they miss one, either the question is unfair or the team has the bug, and either finding is worth the afternoon.
If you’d rather not build the loop yourself, we screen C# candidates against questions like these before a submittal ever reaches your calendar. Talk to a recruiter and we’ll tell you what the market looks like for your stack. We place on a contract or direct hire basis, whichever fits.

