MemoryPack icon indicating copy to clipboard operation
MemoryPack copied to clipboard

Init-only property in CircularReference class is not Deserialized

Open WaveGTO opened this issue 1 year ago • 1 comments

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

WaveGTO avatar Aug 16 '24 15:08 WaveGTO

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

neuecc avatar Sep 10 '24 11:09 neuecc

This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 30 days.

github-actions[bot] avatar Mar 10 '25 00:03 github-actions[bot]