0

I have two different classes in the same C# source code file. At the top is a class named:

static class Persist : object

with the field:

public static List<Weapon> AllWeapons = new List<Weapon>() {
      new Weapon("King's Spatha", 10, 20),
      new Weapon("Nofoot Claw", 7, 11)
      };

Further down the source file in a different class (not nested within the first class):

public static class King

And what I'm attempting to do within that class is the following:

public static Weapon UsedWeapon = Persist.AllWeapons[0];

The problem I have is not with finding out if King.UsedWeapon.ID = "King's Spatha". In fact, this code does work as intended.

The problem is that I don't fully understand what's happening under the hood. Does class Persist exist before class King? Does it matter which class is put above the other in the source code?

Peter Duniho
  • 68,759
  • 7
  • 102
  • 136
  • If it works what exactly is the issue? ^^ I don't know the answer to why this works exactly but I'ld suspect the compiler sees the dependencies of the fields and initializes them in the correct order? You could try to intentionally create a circular dependency and see if it still works ^^ – derHugo Mar 24 '20 at 16:42
  • C# compilers are *multi-pass* which means you can reference classes and methods that have yet to be defined. – trojanfoe Mar 24 '20 at 16:47
  • @derHugo My attempt at a paradoxical loop of both fields referencing each other resulted in both simply equaling "null." Thanks for the suggestion. – Miles_Otyugra Mar 24 '20 at 16:56
  • _Visibility_ of members does not depend on order of compilation. As noted, the C# compiler uses multiple passes so that it determines all of the identifiers in a compilation unit before it tries to _use_ any of them. However, there _are_ dependencies with respect to execution order. See marked duplicates for discussion on both the visibility and initialization order aspects. – Peter Duniho Mar 24 '20 at 17:00

1 Answers1

0

The order of definition does not have any impact. Static classes and fields are 'initialized' when the class is accessed first.

Regarding the question of circular dependencies: If the dependencies are circular, the initialization of an static field will start, but if the dependency comes back to that field in a circular way, before the initialization is completed, the field will be used uninitialized!

Example:

public class X
{
    public X y = Y.x;
}

public static class Y
{
    public static X x = new X();
}

void Test()
{
    X x = new X();
}
  1. Object x is created.
  2. x.y is tried to be initialized with Y.x
  3. Y.x is initialized with a new instance of X
  4. 2nd instance of X is created
  5. Y.x.y is tried to be initialized with Y.x
  6. Initialization of Y.x was already started, but Y.x is still null, so...
  7. Y.x.y is initialized with null.
  8. Y.x is ready with the (incomplete) instance of X
  9. x.y gets the (incomplete) instance of X from Y.x
  10. Instantiation of x is done (x.y == null)
Michael Gehling
  • 569
  • 5
  • 12
  • what if they have circular dependencies? – derHugo Mar 24 '20 at 16:57
  • @derHugo: _"what if they have circular dependencies?"_ -- then bad things can happen. Best-case scenario, a value will be incorrect, the member having its default value instead of the intended one. Worst-case scenario, deadlock will occur as one class attempts to access another while holding an initialization lock, preventing the other class from itself initializing. Fortunately, in C# order of initialization is well-defined, so it's relatively simple for a programmer to avoid creating such bad scenarios. – Peter Duniho Mar 24 '20 at 17:02
  • I added an example with circular dependency with all steps that are executed – Michael Gehling Mar 24 '20 at 17:23