59

given the following code:

public static class Helpers
{
   private static Char[] myChars = new Char[] {'a', 'b'};

   private static Int32 myCharsSize = myChars.Length;
}

Is it guaranteed that myChars will be initialized before I use its length to assign to myCharsSize?

Falko
  • 17,076
  • 13
  • 60
  • 105
Alex
  • 75,813
  • 86
  • 255
  • 348

3 Answers3

71

Yes, they will, please see clause 15.5.6.2 of the C# specification:

The static field variable initializers of a class correspond to a sequence of assignments that are executed in the textual order in which they appear in the class declaration (§15.5.6.1). Within a partial class, the meaning of "textual order" is specified by §15.5.6.1. If a static constructor (§15.12) exists in the class, execution of the static field initializers occurs immediately prior to executing that static constructor. Otherwise, the static field initializers are executed at an implementation-dependent time prior to the first use of a static field of that class.

That being said I think it would be better to do the initialization inside a static type initializer (static constructor).

Klaus Gütter
  • 11,151
  • 6
  • 31
  • 36
Andrew Hare
  • 344,730
  • 71
  • 640
  • 635
  • @Marc - LOL, I posted "yes" so I would be first and then came back with the evidence. Since I can no longer be the FGTW I guess I shouldn't worry about being first anymore :D – Andrew Hare Sep 29 '09 at 20:32
  • You can find the current spec at https://www.visualstudio.com/license-terms/ecma-c-common-language-infrastructure-standards/. – jmlane May 15 '18 at 15:17
  • 6
    What about partial classes? – Sinjai Feb 14 '19 at 20:28
  • 2
    @Sinjai you can check 15.3.1 on the same document: "In these cases, the ordering of members within a type declared in multiple parts is undefined." – uygar.raf Jul 27 '21 at 21:38
  • 1
    IMO one of C#'s design mistakes. They should have made anything but constants illegal in static field initializers and forced you to use static constructors, like they forbid using instance members in instance field initializers. What makes things worse is this works as expected: `const int b = a + 8; const int a = 5;`. But just changing constants to static fields suddenly makes the values different: `static int b = a + 8; static int a = 5;`. b is now 8 instead of 13. – relatively_random Apr 07 '22 at 07:02
18

Hmm... I'm surprised that compiles (it does, I checked). I'm not aware of any guarantee that would make this safe. Use a static constructor...


Edit: I accept (see better answer above) that it will work; but my idea with code is to keep it as simple and obvious as possible. If it isn't obvious that it will work (and it can't be if you have to ask), then don't write it that way...

In particular, problems with relying on field order:

  • it can break if you move code around (which I often do)
  • it can break if you split the code into partial classes

My advice remains: use a static constructor for this scenario.

Community
  • 1
  • 1
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • 1
    +1 This advice is sound - just because you _can_ do something doesn't mean you should. I think that a static constructor is the way to go here even though the language does support this type of field initialization. – Andrew Hare Sep 29 '09 at 20:36
  • Though you can write much more concise code with static property/field initializers (typing the property name once per property instead of twice—once in the definition and once in the static initializer function). In some cases, this could be the difference between a source file fitting on one screen or requiring scrolling to see in full. Depends on what your goal is. If you want to textually lay out the properties in a different order than they need to be initialized, then, yes, a manually-written static initializer function is your only choice. – binki Feb 21 '17 at 04:53
0

At first glance, I wouldn't be sure, and I had to try this out to see if it even compiled.

Given that, I would initialize the value in a static constructor.

Jon Seigel
  • 12,251
  • 8
  • 58
  • 92