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

[WIP] Add support for required and init-only properties #374

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

ardabada
Copy link

@ardabada ardabada commented Feb 13, 2025

Overview

This PR fixes the compilation error CS9035 (required member must be set in the object initializer or attribute constructor) that occurs when using required members with circular reference serialization. In cases when GenerateType.CircularReference is used together with the required keyword, the source-generated code fails to initialize required properties, resulting in a CS9035 error.

Changes

  • Updated Object Instantiation for Circular Reference & Required Members

When deserializing types with circular references that include required members, the source generator now uses an uninitialized object rather than calling the default constructor.

id = reader.ReadVarIntUInt32();
if (value == null)
{
-    value = new Sample();
+    value = (Sample)global::System.Runtime.CompilerServices.RuntimeHelpers.GetUninitializedObject(typeof(Sample));
}
reader.OptionalState.AddObjectReference(id, value);

This ensures that an instance is created without triggering the constructor, thereby allowing the required members to be populated later during deserialization.

  • Handling Init-Only Properties

For classes that contain init-only properties which must be set during deserialization, the generated code now leverages PropertyHelper.SetInitOnlyProperty to assign values. This helper method retrieves the property's setter via reflection, caches the delegate for performance, and then invokes the setter.

 SET:
+   global::MemoryPack.PropertyHelper.SetInitOnlyProperty<Sample, string>(value, nameof(Sample.SomeInitOnlyProperty), __SomeInitOnlyProperty);
    goto READ_END;

NEW:
    value = new Sample()
    {
        @SomeInitOnlyProperty = __SomeInitOnlyProperty
    };

Expression.Lambda.Compile method can be used in PropertyHelper.SetInitOnlyProperty, as in AOT it's implemented via an interpreter. According to this Microsoft blog article, removing Expression.Compile() usage when in native AOT applications is recommended.

TODO

  • Ensure compatibility with [SuppressDefaultInitialization] attribute and default values
  • Ensure AOT compatibility

Related Issues

Fixes #370: Required members with circular reference causes CS9035.

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

Successfully merging this pull request may close these issues.

Required members with circular reference causes CS9035
1 participant