Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.


1 Answers

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...

like image 90
Laoujin Avatar answered Sep 07 '25 05:09

Laoujin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!