readonly fields are not initialized

Issue #254 wontfix
Maurizio Margiotta created an issue

Inside a SerializedMonoBehaviour I have a List of classes that I add trough the editor. When Odin deserializes the list, the readonly fields of the classes inside the list are null. I suppose that is because Odin is deserializing them and not calling the constructor, but this is very annoying. Would be better to instanziate them, and then populate them by deserialization.

Comments (5)

  1. Tor Esa Vestergaard

    This is a fundamental aspect and a core part of serialization/deserialization - the constructor will never be called as part of deserialization, as this can have unpredictable side effects. Instead, you can mark the readonly fields as serialized, so that the values in them will be saved, or you can use .NET's [OnDeserialized] attribute to set your fields (this has the drawback that they can't be readonly), or you can use .NET's ISerializable interface, and use the serialization constructor for that to set your readonly fields (this has the drawback that you must manually save and load the values that have to be serialized in your class).

  2. Maurizio Margiotta reporter

    Thanks for the very detailed reply.

    For the sake of learning, I'm just wondering what kind of unpredictable side effects could cause a parameter-less constructor other then initialize some values that could be later overwritten by the deserialization. I googled quite a bit, and I can't find the reason behind this design.

  3. Tor Esa Vestergaard

    Some constructors do things like calling other events - for example, registering types in global static arrays, and so on - or do other complicated logic depending on all sorts of things. This is bad practice, but people do it, and it might happen, and it isn't the sort of thing that should happen during deserialization. Additionally, it is not always that a default constructor with zero arguments even exists on a type, and we still need to be able to deserialize types where that is the case - and we don't want such radically different behaviour between the cases where there is a parameterless constructor and where there isn't one.

  4. Maurizio Margiotta reporter

    I went on coding with Odin, and despite what we discussed, I keep finding very annoying this situation. When I instantiate a prefab I can use readonly fields in the components (that are deserialized by Unity), but if I have a list of classes (for examples of services) that I want to visually add by the inspector, then I can't use readonly fields, plus I have to add and call an Init method and move all the initialization there. I'd really appreciate if you give a second tough on this. At least for the classes with parameterless constructor.

  5. Tor Esa Vestergaard

    I'm sorry, but there is no possible way we are going to call default constructors as a default part of deserialization, unless they are special constructors meant for deserialization like the ISerializable constructor. It would cause an unbelievable amount of problems and bugs to do so. If you give me some code examples, I can perhaps suggest alternatives or easier ways of doing things, but what you're asking is simply not a thing that will ever happen.

  6. Log in to comment