Skip to content

Mention how non-public fields of inherited classes are serialized #47148

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

adamsitnik
Copy link
Member

@adamsitnik adamsitnik commented Jul 9, 2025

Repro:

using System.Formats.Nrbf;
using System.Runtime.Serialization.Formatters.Binary;

namespace NrbfBestPractices
{
    internal class Program
    {
        static void Main(string[] args)
        {
            using MemoryStream payload = new();
#pragma warning disable SYSLIB0011 // Type or member is obsolete
            BinaryFormatter formatter = new();
#pragma warning restore SYSLIB0011 // Type or member is obsolete
            formatter.Serialize(payload, new Derived(42)
            {
                Text = "Hello, World!",
            });
            payload.Position = 0;

            ClassRecord rootRecord = NrbfDecoder.DecodeClassRecord(payload);
            Derived decoded = new(rootRecord.GetInt32("Base+integer")) // HERE
            {
                Text = rootRecord.GetString(nameof(Derived.Text)),
            };
            Console.WriteLine($"Integer: {decoded.Integer}, Text: {decoded.Text}");
        }
    }

    [Serializable]
    public class Base
    {
        private int integer;

        public int Integer => integer;

        public Base(int _)
        {
            integer = _;
        }
    }

    [Serializable]
    public class Derived : Base
    {
        public string Text;
        public Derived(int integer) : base(integer)
        {
        }
    }
}

Source of confusion:

https://github.com/dotnet/runtime/blob/513ff1acc981118e4b981e965dce614c3b8770f5/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/FormatterServices.cs#L42-L44

https://github.com/dotnet/runtime/blob/513ff1acc981118e4b981e965dce614c3b8770f5/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/FormatterServices.cs#L68

https://github.com/dotnet/runtime/blob/513ff1acc981118e4b981e965dce614c3b8770f5/src/libraries/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/SerializationFieldInfo.cs#L21


Internal previews

📄 File 🔗 Preview link
docs/standard/serialization/binaryformatter-migration-guide/functionality-reference.md BinaryFormatter functionality reference

@adamsitnik adamsitnik requested a review from jeffhandley July 9, 2025 11:13
@adamsitnik adamsitnik requested review from gewarren and a team as code owners July 9, 2025 11:13
@dotnetrepoman dotnetrepoman bot added this to the July 2025 milestone Jul 9, 2025
Copy link
Member

@GrabYourPitchforks GrabYourPitchforks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feels like this deserves a code sample showing how things work.

For example:

[Serializable]
public class BaseClass {
    public int PublicIntField;
    private int NonPublicIntField;

    public BaseClass(int publicIntFieldValue, nonPublicIntFieldValue) {
        PublicIntField = publicIntFieldValue;
        NonPublicIntField = nonPublicIntFieldValue;
    }
}

[Serializable]
public class DerivedClass : BaseClass {
    public string PublicStringField;
    private string NonPublicStringField;

    public DerivedClass(int publicIntFieldValue, int nonPublicIntFieldValue)
        : base(publicIntFieldValue, nonPublicIntFieldValue) {
        PublicStringField = PublicIntField.ToString();
        NonPublicStringField = NonPublicIntField.ToString();
    }
}

Then show an example of serializing both a BaseClass and a DerivedClass, including what values are contained within each payload.

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

Successfully merging this pull request may close these issues.

2 participants