I have a question about the initialization of a list in a pure C# class. Here is my class:
[System.Serializable]
public class BaseValue
{
[SerializeField] float _baseValue;
public float Value => baseValue + CalculateModifiers();
public float baseValue => _baseValue;
List<Modifier> modifiers = new List<Modifier>();
public BaseValue(float baseValue)
{
_baseValue = baseValue;
}
public void AddModifier(Modifier modifier)
{
if (modifier == null) return;
modifiers.Add(modifier);
}
public void RemoveModifier(Modifier modifier)
{
modifiers.Remove(modifier);
}
float CalculateModifiers()
{
float value = 0;
foreach (var modifier in modifiers) // here is where the null ref occurs, on the modifiers list
value += modifier.value;
return value;
}
}
public class Modifier
{
public float value;
public Modifier(float value)
{
this.value = value;
}
}
But I get errors because the list of modifiers in the BaseValue class is null and not instantiated when the game is launched, I donât understand why.
If you have any ideas, I would be happy to read them.
There is no null check in the loop because you can also add null as a modifier to the list, âModifierâ in the Engine class is never instantiated and is null, and Awake and Update do nothing in a pure C# class if you donât call them manually (unless the posted code is not complete).
The source of the issue is that Unityâs deserialization process canât create an instance of BaseValue and assign one to maxForce using the normal flow, because the class has no parameterless constructor.
What it does instead is create an uninitialized object, which means that none of the constructors nor field initializers of the object will be executed!
We do, based on learned understanding about how C# works.
This is done quite commonly. Perhaps youâre confused: Value here is a get-only property. Whenever you attempt to read its value, you use the generated getter accessor method, which computes the value every time. There are also auto-properties like public X Value { get; } which does little more than abstract away access to a compiler-generated field. Initializing a property (like public int Value { get; } = 100;) is done once, and this is where order can matter (this is only for auto-properties, and really just sets the compiler generated field under the hood). But in the case of OPâs code, order does not matter because the value returned is computed when you access the property, every time, and this is not a matter of using a property initializer.
Sometimes I wonder if you actually use Unity, or actually code in C# at all.
I know for a fact it wonât change anything. Inline initialisers are called as part of the constructor. The list will be initialised long before the property can be accessed.
And theyâre accessing a method in a Property, not a âmember declarationâ. Itâs a normal thing to do.