user3472162
user3472162

Reputation:

Initialization of static member objects c#

I have some problems with initialization of static member objects. In my project are 3 class files:

Feat, Class (RPG-style not c# class), and Race.

Each of them has some static member objects that can be accessed by for example Feat.General.MightyBlow, Race.Dwarf, or Class.Base.Warrior while MightyBlow.GetType() -> Feat, Dwarf.GetType() -> Race, and Warrior.GetType() -> Class. A feat can be dependent on other feats, classes and races, same goes with classes and races. Each of those 3 categories is not referenced by a true class/feat/race but by a name string that can be looked up in a dictionary like: Class someClass = Class.Implemented[someClassesName].

Some minimal example:

public static Feat ArmorHeavy = new Feat(
    "ArmorHeavy",
    Req.Feats(ArmorLight.GetName),
);

public static Feat ArmorLight = new Feat(
    "ArmorLight",
    Req.Feats(),
);

As you can see ArmorHeavy needs ArmorLight first to be available and that requirement is only identified by ArmorLight's name (simply a string "ArmorLight").

I get no compiler errors but when run this I get the following error

NullReferenceException: Object reference not set to an instance of an object Feat+Proficiency..cctor ()

I thought during initializing of ArmorHeavy C# reaches the point, where ArmorLight.GetName gets called, now jumping to initialization of ArmorLight and finishing ArmorHeavy after ArmorLight was initialized. This is not the case because if I interchange the position of those two member objects or delete the requirement there will be no errors.

How can I solve this? Please don't tell me that I have to order all feats accordingly.

Upvotes: 4

Views: 3936

Answers (1)

Laoujin
Laoujin

Reputation: 10249

You will have to do exactly that, it is not possible to access a member of a null reference.

But it can be made clearer by using a static constructor:

public static Feat ArmorHeavy;
public static Feat ArmorLight;

static ClassName()
{
    ArmorLight = new Feat("ArmorLight", Req.Feats());
    ArmorHeavy = new Feat("ArmorHeavy", Req.Feats(ArmorLight.GetName));
}

Note that in static ClassName the ClassName is the real name of the class these properties are defined in :)

Another option is take make them Lazy but that's probably too much trouble for merely avoiding the correct initialization order.

Since there are quite alot of these things it might be a good idea to move these kind of properties and dependencies outside the code, for example into XML:

<Feats>
  <Feat Name="Light" />
  <Feat Name="Heavy" Requires="Light" />
</Feats>

And then write some code to read out the XML and initialize your objects.

Your actual XML (or some other format) probably needs to be more complicated then that because multiple dependencies might be required etc.

But that all depends on your requirements of course...

Upvotes: 7

Related Questions