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
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.
Make it yours · 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.
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.
LetterServicecalled by the portal
ShortPayoffLetter(no)
FullPayoffLetter(no, days)
Letterthe parent class
new PayoffLetter("UDC-50213")
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 repoExample 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
QuoteServicebuilds quotes
Old Quote classno constructor written
Quote()added by C#, empty
Quote objectPrice 0 · 0 months
new Quote()
Price: 0
TermMonths: 0
1/9Before: no constructor written, so C# added an empty default constructor.new Quote(): empty.Nothing checked the values. A quote for 0 over 0 months reached a customer.Fix: a parameterized constructor takes the price and term and checks them. The free one is gone.First quote since start-up: .NET runs the static constructor, set-up for the whole class, once.52,000 arrives as new Quote(price).Chaining:: this(price, 36) hands over to the full one.The full one runs first: checks pass, it stores 52,000 and 36. Then the short one's empty body.48 months? Copy constructornew Quote(sent) hands over with this(...): new object, same values.revised.ChangeTerm(48) changes only the copy. The quote the customer has still says 36.Static ran once. Every went through the checked constructor. The copy is its own object.
In plain words
A finance quote is a dealer's offer to a BMW FS customer: the car's price and how many months to pay. In code it is a , built from the class with .
A constructor is the check-in desk every new object passes. makes the empty object, the constructor fills it in and checks it, and only then do you get it. If the constructor says no, there is no object. shows this step by step.
Default constructor: one with no parameters. If you write no constructor at all, C# quietly adds an empty one. Write any constructor yourself and that free one disappears.
Parameterized constructor: one that asks for values, like the price and the months, and checks them before the object exists.
Chaining: a short form that fills in the usual answer and passes you to the full form. passes to another constructor in the same class. passes to the parent class's constructor (). The one you pass to runs its body first; the one you started at finishes last.
Copy constructor: a photocopy. It takes an existing quote and builds a new one with the same values. You write on the copy; the original stays as it was. C# writes one for you only for records (a kind of class made for data), and the keyword (copy this record, changing one value) uses it.
Static constructor: switching the office lights on, once, when the first person arrives. It belongs to the class, not to any one object (). It runs by itself, once, before the class is first used. It never takes parameters, and has no or in front.
Private constructor: a staff-only door. () means only code inside the class can call , so the class decides how its objects are made: for example exactly one shared object, called a singleton, or a factory method, a static method like that builds the object for you.
Order: static constructor first, and only once. Then, for every object: field initializers (a starting value written on the same line as a field or property, like = Guid.NewGuid(), which makes a new unique id), the parent's constructor, then this constructor's body.
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.
QuoteServicedealer requests
Quote classstatic part
Buildshort, full, copy
Objectsquotes in memory
app started
1/1008:00 the API starts. Nothing about runs yet: no one has used it.Static. 08:41, first quote of the day. Before anything else, static Quote() runs once.Chaining.new Quote(52_000m) runs the short constructor, which hands over with this(price, 36).Field initializer. At the end of the chain, Id = Guid.NewGuid() runs first.Base. Then the parent's constructor. has no parent we wrote: it is object's, empty.Parameterized. The full body checks 52,000 and 36, and stores them. Then the short body, empty.08:55, the second quote: no static step this time. It ran once, for the life of the app.Copy. 09:10, the first customer wants 48 months. new Quote(sent) makes a new object, new .Default. A new test writes new Quote(). It doesn't compile: the free empty constructor is gone.Recap: static once; then chaining, field initializer, base, body. Copy: new object. Default: gone.
The story
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.
Dealer portalchecks the price
Mobile appchecks the price
Nightly importno check
new Quote()then fill in values
1/4Before: three parts of the system build quotes. Each makes an empty one, then fills it in.Each part has its own copy of the price check. The nightly import's copy was never written.A dealer file has a blank price. The import builds the quote anyway, and it is emailed out.Fix: the constructor checks the values, and throws an error if one is bad. All three go through it.
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.
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:
CallerQuoteService
.NETruns new
Checksin Quote
The objectin memory
new Quote(52,000, 36)
1/6The caller writes new Quote(52_000m, 36)..NET makes room for one in memory, every value 0. Nobody can see it yet.Then it runs the constructor whose parameters match the call: the checks in .The constructor checks the values. They pass, so it stores them in the object.Only now does the caller get a (the address) to a ready quote.Price 0: the check throws , C#'s error for a bad value. No reference comes back.
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.
ReportedIf a class has a static constructor and a default constructor, which runs first?
The static one, once, just before the class is first used. The default one runs on every , after it. Two calls in a row run the static one once and the default one twice.
classSample
{
static Sample() { } // oncepublic Sample() { } // every new
}
newSample(); // static, then defaultnewSample(); // default only
ReportedCan a constructor be private? Why would you make one?
Yes. Then only code inside the class can call . The class decides how its objects are made: for a singleton it makes exactly one itself and hands it out. Other uses: a factory method (a static method like that builds the object for you), and a class of only static helpers, though a says that more clearly.
publicclassRateCard
{
publicstatic RateCard Instance { get; }
= newRateCard();
private RateCard() { }
}
RateCard a = RateCard.Instance;
// fine: the one shared objectRateCard b = newRateCard();
// compile error: the constructor// is private (CS0122)
ReportedWhat is constructor chaining, and why use it?
One constructor calling another before its own body runs: for another constructor in the same class, for the parent class's. The point is one place for the checks. Short constructors fill in defaults and hand over, so a new rule reaches every way of building the object.
Answer, then open the next level. That is the order an interviewer digs in.
Reporteda candidate was asked Intervieweran interviewer asks it
ReportedIf a class has a static constructor and a default constructor, which runs first?
The static one, once, just before the class is first used. The default one runs on every , after it. Two calls in a row run the static one once and the default one twice.
classSample
{
static Sample() { } // oncepublic Sample() { } // every new
}
newSample(); // static, then defaultnewSample(); // default only
On .NET, each class's static constructor runs at that class's first use, so with TruckQuote : Quote the child's runs first. The diagram walks it. The C# docs don't promise an order between classes, so never write code that depends on it.
Programnew TruckQuote
TruckQuotechild
Quoteparent
new
Truck static
1/4new TruckQuote(...) is the first use of TruckQuote: its static constructor runs.Then TruckQuote's field initializers, before any parent code.Calling the parent's constructor is the first use of Quote: its static, field, body.Back in TruckQuote: its constructor bodies run last.
When exactly does a static constructor run?
Just before the first object of the class is built, or the first time a static member is used, whichever comes first. If the class is never used, it never runs. If two requests arrive at once, .NET lets one run it and makes the other wait.
ReportedCan a static constructor have parameters, or be public?
No to both. Nobody calls it, so nobody could pass a value: static Quote(int x) is error CS0132, "a static constructor must be parameterless". public static Quote() is error CS0515. A class has at most one.
ReportedCan a constructor be private? Why would you make one?
Yes. Then only code inside the class can call . The class decides how its objects are made: for a singleton it makes exactly one itself and hands it out. Other uses: a factory method (a static method like that builds the object for you), and a class of only static helpers, though a says that more clearly.
publicclassRateCard
{
publicstatic RateCard Instance { get; }
= newRateCard();
private RateCard() { }
}
RateCard a = RateCard.Instance;
// fine: the one shared objectRateCard b = newRateCard();
// compile error: the constructor// is private (CS0122)
QuoteServiceerror CS0122
class RateCardprivate RateCard()
1/3 tries new RateCard(). The constructor is private, so it doesn't compile.Inside the class, the static Instance line can call it. It runs once and builds the one object.Everyone reads and gets the same object.
Not when all its constructors are private, as here. A child's constructor must call a parent constructor, and a private one can't be reached: class BigRateCard : RateCard fails with CS0122. A class written inside could, because it counts as inside.
Why not…Would you hand-write a singleton in a .NET API?
Rarely. I register the class with in Program.cs (). The container builds one object and hands it to every class that asks, the class keeps a normal constructor, and a test can pass in a fake. A static Instance can't be swapped in a test.
Is that static Instance safe with many threads?
Yes. Instance gets its value from a static field initializer (no static constructor needed). That is part of the class's one-time static setup, which .NET runs once, on one , while any other thread that needs the class waits.
ReportedWhat is constructor chaining, and why use it?
One constructor calling another before its own body runs: for another constructor in the same class, for the parent class's. The point is one place for the checks. Short constructors fill in defaults and hand over, so a new rule reaches every way of building the object.
The one you chain to. new Quote(52_000m) runs the full constructor's body first, then the short one's. With , the parent's body runs before the child's.
With , do field initializers run twice?
No. They run once per object, in the constructor at the end of the chain, the one that calls the parent. A real run gives each quote one .
What if I write no ?
C# adds for you: the parent's constructor with no parameters. If the parent has none, the child doesn't compile: error CS7036, "no argument given that corresponds to the required parameter".
ReportedDoes C# have a copy constructor?
Not one it writes for you, for a class. You write a constructor that takes the same type. Records are different: the compiler writes a copy constructor, and uses it, so quote with { TermMonths = 48 } is a new record with one value changed.
Whatever you write. Copying a list field copies only the , so both objects share one list: a shallow copy. Copy the list itself too.
Why not…Why not or ?
is a shallow copy, and it is , so only the class or a child can call it. never says whether its copy is deep or shallow, so Microsoft's design guidelines say not to use it in public APIs. A copy constructor shows exactly what is copied.
What happens if a static constructor throws?
The class is broken until the app restarts. The first use throws with the real error inside it, and every later use throws the same one, because .NET never runs the static constructor again. Only a restart fixes it.
System.TypeInitializationException: The type
initializer for 'Quote' threw an exception.
---> System.TimeoutException: Execution
Timeout Expired.
Why not…Can a constructor call a virtual method?
It can, but don't: the parent's constructor would run the child's version before the child's constructor body has run, so anything set there is still 0 or null. The walks it.
What is a primary constructor?
C# 12 lets you write parameters on the class line, public class QuoteService(TermCatalog terms). Common for services that get their parts from the DI container. The full answer, and why business objects keep a normal constructor, is on the .
Production bugs, and how to tell them
Each one: what you see, why, the fix in code, and the line to say.
Quick quotes skipped the new credit rule
Audit finding, BMW FS credit risk:
14 quotes over $250,000 were made in the
portal, which must refuse them (a credit
manager handles those). All 14 came from
the Quick quote screen.
(no exception, no error log)
Cause
had two constructors, and each had its own copy of the checks. A new rule, "the portal refuses quotes over 250,000; a credit manager handles those outside it", was added to the full constructor only. The Quick quote screen calls new Quote(price), the short one, so the rule never ran.
Fix
The short constructor keeps no checks of its own and chains with : this(price, 36). Every rule now lives in one constructor. A test builds a Quick quote over 250,000 and expects it refused.
Diagram · step 1Before: two constructors, and each has its own copy of the price check.
class Quotetwo constructors
Quote(price)own copy: price > 0
Quote(price, term)price > 0
Before · Quote.cs · line 1 · 1 of 4The full constructor, with its own price check.
Say it
We had copied the checks into two constructors, and one copy went stale when a rule was added. Chaining puts every check in one constructor, so any new rule reaches every way of building a quote. The test proves the short path runs it too.
A revised quote changed the one the customer had
Customer email, BMW FS dealer support:
"My quote from Friday now lists Tyre and
rim cover. I never asked for it."
(no exception, no error log)
Cause
gained an (add-ons such as a ). The copy constructor did Extras = other.Extras, which copies the , not the list. Both quotes pointed at one list, so adding tyre cover to the revision added it to the sent quote, and the same request saved both.
Fix
Copy the list itself: new List<string>(other.Extras) builds a new list holding the same items (it is List's own copy constructor). A test adds to the copy and checks the original still has one extra.
Diagram · step 1The sent quote holds a reference to its list of extras: one .
sentExtras →
List of extrasService plan
Before · Quote.cs · line 1 · 1 of 2The add-ons on this quote. Each quote should own its list.
Say it
Our copy constructor was a shallow copy: it copied the reference to the list, not the list. Both quotes shared it, so changing the revision changed the sent quote. Now the constructor copies every list the quote owns, and a test proves the original doesn't change.
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
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.
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).
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.
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.
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.
Truck quotesNavistar dealers
Server 1Quote ready
Server 2Quote broken
Server 3Quote ready
Azure SQLTermOptions table
Failed requests: 31%
09:40: all from server 2
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
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().
In Program.cs, write new Quote() three times, each inside its own try / catch that prints the exception's type.
Run it: "static ran" prints once, then three times.
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."
SourcesSourced: 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
Don't sayEvery class has a default constructor.SayOnly a class with no constructor written. Write any constructor and the free one is gone.
Don't sayThe static constructor runs every time you create an object.SayOnce per class, for as long as the app runs, before the class is first used.
Don't sayWith chaining, the constructor you called runs first.SayThe one it chains to runs first. The one you called finishes last.
Don't sayThe parent's static constructor always runs before the child's.SayOn .NET, new Child() runs the child's static constructor first; the parent's runs when the parent is first touched. The docs don't promise an order, so don't depend on it.
Don't sayA copy constructor copies everything.SayIt copies what you write. Copy a list field and both objects share one list; copy the list too.
Traps
What should you say instead? Tap to check.
Don't sayEvery class has a default constructor.
Say instead
Only a class with no constructor written. Write any constructor and the free one is gone.
Don't sayThe static constructor runs every time you create an object.
Say instead
Once per class, for as long as the app runs, before the class is first used.
Don't sayWith chaining, the constructor you called runs first.
Say instead
The one it chains to runs first. The one you called finishes last.
Don't sayThe parent's static constructor always runs before the child's.
Say instead
On .NET, new Child() runs the child's static constructor first; the parent's runs when the parent is first touched. The docs don't promise an order, so don't depend on it.
Don't sayA copy constructor copies everything.
Say instead
It copies what you write. Copy a list field and both objects share one list; copy the list too.
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.
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
What is the first use of TruckQuote? Of Quote?
Field initializers run before which constructor call?
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.
Programtwo new calls
TruckQuotethe child
Quotethe parent
new TruckQuote(90,000)
Truck static
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.
Where does the one object live so everyone can reach it?
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.