← Home
.NETOOP and C# basicsReported by candidates

What are the types of constructors in C#? What do static and private constructors do, how does chaining work, and which runs first?

16 reports in the question index (8 linked below), mostly first technical rounds: Infosys (3 reports), Capgemini, Zobi Web Solutions, Sdaemon Infotech, Gif Technologies and others. Often asked as one question, so it is one card.

Say this first · about 30 seconds
Make it yours · UDC Finance payoff letters (invented example)
The code, simplified

Invented to show the shape, in C#. Tap Next to walk one letter for contract UDC-50213 through its constructors.

UDC.sln · where these 3 files sit
  • Letters/
Diagram · step 1A customer asks to pay off contract UDC-50213. The service calls the short constructor.
LetterService.cs · line 7 · 1 of 2Builds the letter with one value. The portal calls with "UDC-50213" when the customer taps Pay off early.

Fix later in your repo Example written for this card: invented, not from a real codebase.

Say it out loud, then check

Show the 30-second answer
  • A constructor is the code that runs when you write . It has the class's name and no return type, and its job is to make sure the object is valid from the moment it exists. On our BMW FS lending API, a can't be built without a price above zero and a term we offer.
  • If you write no constructor, the compiler adds an empty default one with no parameters, but as soon as you write your own, that free one is gone. Ours is a parameterized constructor: it takes the price and the term, checks them, and stores them.
  • We also chain constructors. A short one that takes only the price calls the full one with , passing 36 months, so every check lives in one place. The full constructor's body runs first, and the short one, the one called, finishes last. A child class does the same with to call its parent's constructor.
  • For revised quotes we wrote a copy constructor, which takes another quote and copies its values, because C# doesn't generate one for a class. That way the quote the customer already has never changes. And I copy any lists inside it too, not just the reference to them.
  • A static constructor runs once per class, by itself, before the class is first used, and it takes no parameters and no access modifier. So between a static and a default constructor, the static one runs first, once, and the default one runs on every . The full order is: static constructor, field initializers, base constructor, then the body.
  • A private constructor means only the class itself can call ; that is how you write a singleton or a factory method, though in an API I'd rather register a singleton in the . And I never do risky work in a static constructor: if it throws, the class stays broken until the app restarts. We lost a server for truck quotes that way.
Check your answer: tick what you said

You said 0 of 8

Then add your example: UDC Finance payoff letters (invented example)
  • Situation: at UDC Finance in New Zealand, a customer can ask the portal what it costs to pay a contract off early. The answer goes out as a letter. Every letter must name its contract, and a letter is valid for 7 days unless staff set another number. Each screen used to build letters its own way, and two had lost a check.
  • What I did: a parent class, , whose constructor checks the contract number. inherits from it and has two constructors. The short one fills in 7 days and hands over with . The full one passes the contract number up with , then checks the days.
  • Result: whichever constructor a screen calls, both checks run, and each is written once. A new kind of letter, like an arrears letter about missed payments, gets the contract check for free.
  • What I'd say: chains inside one class, chains to the parent. The parent's body runs first, then the full constructor, then the short one.

See it

1/9Before: no constructor written, so C# added an empty default constructor. new Quote(): empty.

In plain words

The senior answer · about 2 minutes
The types, in my words
  • A constructor's job is to make sure an object is valid from the moment it exists. On our BMW FS lending API, a can't be built without a price above zero and a term we offer, because the constructor checks both and throws otherwise.
  • The default constructor is the empty one the compiler gives you when you write none. I rarely keep it on business objects, because an empty quote is a bug waiting to happen. Writing the parameterized constructor removes it automatically.
  • Chaining is how I keep one door. The short constructor, price only, chains with : this(price, 36) to the full one, and the copy constructor chains there too. So when credit risk added a new rule, it went into one constructor and every way of building a quote got it. We learned that the hard way; it is the first bug below.
  • C# has no automatic copy constructor for classes. I write one when a screen needs to change a copy and keep the original, like a revised quote. The trap is lists: copying the field copies the reference, so both objects share the list. I copy the list too.
Static and private
  • A static constructor runs once per class, before first use, and .NET makes sure only one runs it. I keep it to cheap, safe work like building a lookup in memory. In most classes a static field with a starting value is enough.
  • The trap is failure. If a static constructor throws, .NET never runs it again: every later use throws until the app restarts. That is what took one of our three servers out for truck quotes for four hours; it is the production incident further down.
  • A private constructor means only the class can build itself. The textbook use is a singleton, and it also blocks inheritance. In an ASP.NET Core API I register the class as a singleton in the instead, so a test can hand in a fake.
The order, and the trick question
  • Static first, once. Then, for every : field initializers, the base class constructor, and the body. With chaining, the constructor you chain to finishes before the caller's body.
  • The trick is static constructors with inheritance. On the first new TruckQuote(), TruckQuote's static constructor runs first, then its field initializers, and only then Quote's static constructor, when Quote is first touched. Many people say parent first; a real run on .NET says otherwise, and the second live task shows it. The docs don't promise an order between classes, so I never write code that depends on it.
In production
  • No I/O (input and output: the database, files, the network) in static constructors, ever. Load that at start-up in a normal class, with retries, so a failure shows at deploy time, not on every request.
  • What I left behind after the incident: a test that builds a quote through every constructor and expects the same checks, and a review rule that a static constructor touching the network is rejected.

One morning, every constructor

The BMW FS dealer portal, in time order. Each step names the kind of constructor at work.

1/1008:00 the API starts. Nothing about runs yet: no one has used it.

The story

  1. Before

    A finance quote is a dealer's offer to a BMW FS customer: the car's price and the months to pay. Three parts of the system build quotes: the dealer portal, the mobile app and a nightly import of dealer files. Before, had no of its own (a constructor is the code that runs when builds an object). Each part built an empty quote and filled it in, each with its own checks.

    1/4Before: three parts of the system build quotes. Each makes an empty one, then fills it in.

  2. Why it had to change

    When building an object and checking it are two separate steps, one path will skip the check one day. The compiler can't warn you, because an empty quote is perfectly legal code.

  3. How it works now

    A constructor makes building and checking one step: can't hand out the object until the constructor has finished. Here is what .NET does for one , step by step:

    1/6The caller writes new Quote(52_000m, 36).

  4. What we gained

    One checked door for every path, and an empty new Quote() doesn't compile any more. The rest of the card shows the other kinds of constructor; every one of them goes through that same door.

In the lending API

The four constructors of . Each marked line is one constructor type; the diagram above shows them running.

Only the key lines are shown; Deep walks the whole file.

Lending.sln · where this file sits
  • src/Domain/Quotes/
⋯ 11 lines in Deep⋯ 3 lines in Deep⋯ 9 lines in Deep
Quote.cs · line 8 · 1 of 4The static constructor. No , no parameters, and no code calls it: .NET runs it by itself, once, just before the first is built (the call comes from , shown in Deep).

The code, file by file

The quote class from the lending API and the service that calls it. Tap Next to walk the diagram with the code: one quote started, then copied.

Lending.sln · where these 2 files sit
  • src/
    • Application/Quotes/
    • Domain/Quotes/
QuoteService.cs · line 1 · 1 of 5namespace: a name that groups related classes, like a folder. Application: the jobs the business runs. The quotes controller, which receives the dealer portal's web requests, calls this class.

What they ask next

The follow-ups interviews really ask. Answer out loud, then tap to check.

Follow-up tree

Answer, then open the next level. That is the order an interviewer digs in.

Reporteda candidate was asked Intervieweran interviewer asks it

Production bugs, and how to tell them

Each one: what you see, why, the fix in code, and the line to say.

Production incident: One server failed every truck quote for four hours

P2 · serious, has a workaroundNavistar Financiallatent: hidden for weeksQuote API behind the Navistar dealer portal

Composed, not a real event at Navistar Financial. The mechanism is real C#, checked by a run on .NET 10: if a static constructor throws, .NET never runs it again, and every use of that class throws `TypeInitializationException` until the process restarts. Times, counts, names, ticket and PR numbers are composed.

The story in 5 lines
  1. On Tue 13 Oct, from 06:02 CT, about a third of truck quotes in the Navistar dealer portal failed with an error. Dealers who tried again often got through, so it looked flaky.
  2. The quote API runs on three servers ( instances: copies of the app on separate machines). Overnight, Azure restarted server 2, in the same window as a planned failover (the database switching to its standby copy, with a few minutes of errors).
  3. Release 5.8 had changed 's static constructor to load the allowed terms from , so Navistar could offer 84-month truck terms. Server 2's first quote ran it mid-failover, and the query timed out.
  4. A static constructor that throws is never run again. Every quote on server 2 then failed with , long after the database was back at 06:10.
  5. Restarting server 2 at 10:05 stopped it. The fix: load the terms at start-up, with retries, in an ordinary class, and keep static constructors free of database calls.
Who's who (4 people)
You
.NET developer on the vendor team. Finds the cause, writes the fix.
Tech lead
Vendor senior. Reviews every change, runs the postmortem.
L2 pod
Vendor support. First look, runs the log queries, restarts servers.
Navistar dealer support lead
Takes the dealers' calls. Decides what dealers are told.

Tap a step. The map lights the place where it happens.

1/4 Detect

Detect: a third of truck quotes fail. The database is back at 06:10, but the failures go on.

Tue 13 Oct, 06:15 CT (16:45 IST)Azure Monitor alert, then the L2 pod

  • What: an fires: 31% of requests to the quote API are failing. Navistar dealer support starts getting calls: "truck quotes fail, then work when I retry".
  • Why it hid: an failover had been announced for 06:00 to 06:10. Everyone read the errors as the failover and waited. At 06:10 the database was healthy, and the errors did not stop.
  • How we saw it: at 09:40 split the failures by server with the query below, in , the query language of (Azure's store for the app's logs and errors). Every failure came from server 2, and every one was the same exception.
App Insights: failures by server
exceptions
| where timestamp > ago(6h)
| where cloud_RoleName == "quote-api"
| summarize count()
    by cloud_RoleInstance, type
| order by count_ desc
In theory

An alert that splits failures by server, so one bad server out of three stands out in minutes.

In practice

The alert counted failures for the whole API, so one bad server looked like a flaky database. It took three and a half hours to split them.

Try it yourself · 10 minutes, on your Mac
  1. dotnet new console -n StaticLab. Add a class with static Quote() that prints "static ran" and then throws new TimeoutException(), and an empty public Quote().
  2. In Program.cs, write new Quote() three times, each inside its own try / catch that prints the exception's type.
  3. Run it: "static ran" prints once, then three times.
  4. Move the throw into a normal method and call that three times instead: each call fails on its own, and nothing stays broken.
You should see

A static constructor gets one try per process. If it fails, the class stays broken until a restart.

The senior move

"Static constructors get one try per process, so I keep them to in-memory work. Anything that can fail, like the database, loads at start-up with retries."

Sources Sourced: a static constructor runs at most once, and if it throws, the type stays unusable and every use throws TypeInitializationException (C# docs, "Static constructors"; .NET API docs, TypeInitializationException). Checked with a real run on .NET 10. Composed: Navistar Financial's systems, dates, counts, names, ticket and numbers, and the (standard columns).

Traps

Traps

What should you say instead? Tap to check.

Live coding

Easy first, then harder. Set a timer and type it before you look.

Task 1

Reportedeasy · 15 minutes

Write a class: a constructor that takes the price and the term and checks them, a price-only constructor that chains to it with 36 months, and a copy constructor. Prove with tests that the short one gives 36 months and that a copy is a separate quote.

Zobi Web Solutions: write a sample constructor and name its types
Stuck? Hints
  1. Which constructor should hold the checks? Make the others hand over to it.
  2. How does one constructor call another of the same class?
  3. How can you prove the copy is a different object, not the same one?
Show a solution
Lending.sln · where this file sits
  • tests/Domain.UnitTests/
QuoteTests.cs · line 5 · 1 of 4Proves the chain filled in the default.
What the interviewer checks
  • Checks live in one constructor; the others use .
  • decimal for the price.
  • A copy test that changes the copy and checks the original.
  • Can say why the empty new Quote() no longer compiles.
  • Senior extra: names the shallow-copy trap if the class held a list.

Task 2

Question index: Mustmedium · 10 minutes

Predict what this program prints, line by line, before you run it. Then explain why Quote's static constructor prints after TruckQuote's.

Question index: predict the output. Asked as "static or default constructor first?" at Sdaemon Infotech
You are given

prints a line and returns 0, so a field's starting value can print when it runs.

Lending.sln · where these 4 files sit
Stuck? Hints
  1. What is the first use of TruckQuote? Of Quote?
  2. Field initializers run before which constructor call?
  3. With , whose body finishes last?
Show a solution
Lending.sln · where this file sits
Diagram · step 1First new TruckQuote(...): the first use of TruckQuote, so its static constructor runs.
Output (real run) · line 2 · 1 of 7The first use of TruckQuote is this , so its static constructor runs before anything else.
What the interviewer checks
  • Child static before parent static on .NET, and says why (first use); knows the docs don't guarantee it.
  • Child field initializer before the parent's constructor.
  • The full constructor's body before the short one's.
  • No static lines on the second .

Task 3

Question index: Mustmedium · 15 minutes

Write as a singleton: one object for the whole app, built by a private constructor. Then give the app one through the DI container instead, and say which you would choose and why.

Global Quest Solutions: is a private constructor possible? Use cases
Stuck? Hints
  1. Who is allowed to call a private constructor?
  2. Where does the one object live so everyone can reach it?
  3. Which method makes the container keep one object?
Show a solution
Hand-written · RateCard.cs · line 3 · 1 of 3The one object, reached through the class name: .
What the interviewer checks
  • constructor and a static Instance.
  • Knows the static setup is thread-safe without a lock.
  • DI version: a normal public constructor and .
  • Picks DI for an API, and says why: a test can pass in a fake.
With AI tools

Interviewers now ask how you check AI-written code. When I review constructors an assistant wrote, I look for three things: a copy constructor that assigns a list field straight across (a shallow copy), a static constructor that reads settings or the database "so it loads once", and a hand-written singleton where would do. And for order-of-execution questions I run the code instead of trusting the chat answer: the child-static-first order is easy to state wrong, and the docs don't even guarantee it.

Glossary: every name, one line each →

My notes

Paste the NOTES block from your doubt chat here. The grader never reads notes; the coach reads "Still unclear".

Read moreWhere it was asked