Aug 31, 2023

Structs in C# are fun - Part 3/9: Field initialization in structs

Leia este post em português

Lisez cet post en french.

  1. Structs in C# are fun.
  2. Brief introduction to Value Types vs Reference Types.
  3. Field initialization in structs (this post).
  4. Constructors and struct behavior.
  5. Other scenarios in which struct constructors behavior may surprise you.
  6. Struct with default argument values in constructors, a.k.a, are you not confused yet?
  7. `required` feature from C# 11 will not save your a** job.
  8. Struct used as default argument values.
  9. Bonus: Struct evolution in C#.

Continuing with our series on Value Types, given the code below, what do you expect it to print (I recommend trying to answer without running it first):

If you answered 0 (zero) you nailed it and probably already have a good understanding of how .NET/C# handles value type instantiation / field initialization; by the other hand, if you answered 32 you may have been tricked.

In this post I'll briefly discuss one of the aspects that leads to this behavior: field initialization in .NET, or to be more precise, in C#.

In an oversimplified way, whenever C# compiler finds a field initialization it will simply move the initialization code to the constructors, i.e, initializing a field is equivalent to setting its value in the constructors (static fields are initialized in static constructors), so given the code below:

the C# compiler will process it as it was written as:

which you can confirm in the generated IL below, but keep the following in mind if you're not familiar with IL code:

  1. There's no need to be daunted by its apparent complexity.
  2. I've included comments to emphasize the key parts.
  3. I've omitted certain less crucial specifics.
  4. Grasping all the details isn't important to understand the main concept.

Lines 6~22 and 25~36 defines, respectively, the constructor taking no parameters and the one taking an integer;  note that the code related to field initialization (`f = 42`) has been introduced in both (lines 9~11 and 29~31).

In the next post we'll start exploring struct constructor behavior, a.k.a, the second part of the puzzle that explains why the program at the top of the post prints 0.

As always, all feedback is welcome.

Have fun!

No comments: