Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Init-only property in CircularReference class is not Deserialized #322

Open
WaveGTO opened this issue Aug 16, 2024 · 1 comment
Open

Init-only property in CircularReference class is not Deserialized #322

WaveGTO opened this issue Aug 16, 2024 · 1 comment

Comments

@WaveGTO
Copy link

WaveGTO commented Aug 16, 2024

Expected Behavior

Deserialization behaviour of init-only properties should be independent of the GenerateType and deserialize correctly for CircularReference-annotated types.

Current Behavior

Init-only properties in CircularReference-annotated types are not deserialized

Workaround

Don't serialize Init-only properties and use a private backing field for (de-)serialization.

Steps to Reproduce

using MemoryPack;

namespace MemoryPackTest
{
	internal class Program
	{
		static void Main(string[] args)
		{
			TestCircularInitOnlyPacking();
			return;
		}

		static void TestCircularInitOnlyPacking()
		{
			MyCircularType instance = new() { Test = 2 };
			byte[] bytes = MemoryPackSerializer.Serialize<MyCircularType>(instance);
			MyCircularType? result = MemoryPackSerializer.Deserialize<MyCircularType>(bytes);

			Console.WriteLine(instance.Test);	// Output: 2
			Console.WriteLine(result?.Test);	// Output: -1
		}
	}


	[MemoryPackable(GenerateType.CircularReference)]
	internal partial class MyCircularType
	{
		[MemoryPackOrder(0)]
		public int Test { get; init; } = -1;
	}
}

Cause

It is caused by the Generated Deserializer calling the parameter-less constructor without any object initializers.
This only happens with CircularReference types, as they are constructed separately for the ref-handling system, before the properties are set:
image

Additionally, since such an object's value is never null after this, the generated NEW path is redundant and never taken:
image

The SET path can't do anything, because the property is init-only:
image

Comment

I am not sure if this is intended. If it is, it should be stated clearly in the ReadMe.
If this is a bug, this might not be that easy to fix.
A possible fix could be to first deserialize all init-only properties and then to construct the object.
This would probably lead to issues if an init-only property type contains a circular reference to this object, but maybe that could be caught by a compiler check.
In any case, thank you for this project. Other than this, it was quite easy to integrate into my codebase :D

@neuecc
Copy link
Member

neuecc commented Sep 10, 2024

Thanks for the detailed report, this looks like a problem that needs to be fixed.
I'll give it a try.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants