Serialization and Inheritance in C#

What is Serialization in Inherited Classes?

Serialization in **inherited classes** allows a **derived class to be serialized**, including all properties and fields from its **base class**. Proper handling ensures that both **public and private members** of a base class are correctly serialized.

Key Features of Serialization in Inherited Classes

  • The **[Serializable]** attribute must be applied to both **base and derived** classes.
  • Base class **private fields are not serialized** unless explicitly handled.
  • Use **ISerializable** for custom serialization of base class members.
  • Supported in **Binary, XML, and JSON serialization**.

Basic Serialization with Inheritance

If a **base class is serializable**, all **public and protected members** are automatically serialized.

Example: Binary Serialization with Inheritance

using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

[Serializable]
class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

[Serializable]
class Employee : Person
{
    public int EmployeeID { get; set; }
}

// Writing Binary Data
class Program
{
    static void Main()
    {
        Employee emp = new Employee { Name = "Alice", Age = 30, EmployeeID = 1001 };
        BinaryFormatter formatter = new BinaryFormatter();

        using (FileStream stream = new FileStream("employee.dat", FileMode.Create))
        {
            formatter.Serialize(stream, emp);
        }

        Console.WriteLine("Inherited class serialized successfully.");
    }
}

// Output:
// Inherited class serialized successfully.
        

The **Employee** class inherits **Person**, and all **public and protected** fields are serialized.

Handling Private Fields in Base Class

Private members of a **base class** are **not automatically serialized** in derived classes.

Example: Custom Serialization for Private Fields

using System;
using System.IO;
using System.Runtime.Serialization;

[Serializable]
class Person
{
    private string _secretCode = "1234";
    public string Name { get; set; }
    public int Age { get; set; }

    public string GetSecretCode() => _secretCode;
}

[Serializable]
class Employee : Person
{
    public int EmployeeID { get; set; }
}

// Writing Binary Data
class Program
{
    static void Main()
    {
        Employee emp = new Employee { Name = "Bob", Age = 40, EmployeeID = 2001 };
        IFormatter formatter = new BinaryFormatter();

        using (FileStream stream = new FileStream("employee_secret.dat", FileMode.Create))
        {
            formatter.Serialize(stream, emp);
        }

        Console.WriteLine("Private fields in base class are NOT serialized.");
    }
}

// Output:
// Private fields in base class are NOT serialized.
        

**Private fields** are not serialized automatically, but can be included using **ISerializable**.

Using ISerializable for Custom Serialization

Implementing **ISerializable** in the base class allows **full control over serialization**, including **private members**.

Example: Custom Serialization Using ISerializable

using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

[Serializable]
class Person : ISerializable
{
    private string _secretCode = "9876";
    public string Name { get; set; }
    public int Age { get; set; }

    public Person() { }

    protected Person(SerializationInfo info, StreamingContext context)
    {
        _secretCode = info.GetString("SecretCode");
        Name = info.GetString("Name");
        Age = info.GetInt32("Age");
    }

    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue("SecretCode", _secretCode);
        info.AddValue("Name", Name);
        info.AddValue("Age", Age);
    }

    public string GetSecretCode() => _secretCode;
}

[Serializable]
class Employee : Person
{
    public int EmployeeID { get; set; }
}

// Writing Binary Data
class Program
{
    static void Main()
    {
        Employee emp = new Employee { Name = "Charlie", Age = 35, EmployeeID = 3001 };
        BinaryFormatter formatter = new BinaryFormatter();

        using (FileStream stream = new FileStream("employee_custom.dat", FileMode.Create))
        {
            formatter.Serialize(stream, emp);
        }

        Console.WriteLine("Private fields in base class are serialized using ISerializable.");
    }
}

// Output:
// Private fields in base class are serialized using ISerializable.
        

Implementing **ISerializable** allows **custom serialization** of private fields.

Best Practices for Serialization in Inheritance

  • Use **[Serializable]** for automatic serialization in both base and derived classes.
  • Implement **ISerializable** in base classes to **serialize private fields**.
  • For **XML and JSON serialization**, ensure **public properties** are properly defined.
  • Handle **versioning carefully** when modifying serialized base class structures.