C# inheriting correctly in editor, but loses it run-time

Here is a sample of the inheritance I am using:

public interface A
{
    void Foo();
};

[System.Serializable] // otherwise creates no object
public class B : A
{
    public virtual void Foo() { Debug.Log("B"); }
};

[System.Serializable] // otherwise creates no object
public class C : B
{
    public override void Foo() { Debug.Log("C"); }
};

// Inheritance lost during run-time.
[System.Serializable]
public class StoreB : Monobehaviour
{
    public List< B > listB = new List< B >();

    private void Start()
    {
        foreach( B obj in listB )
        {
            if( obj.GetType() == typeof( C ))
            {
                // this is false
            }

            obj.Foo(); // outputs B
        }
    }
};


// Inheritance works fine here.
public class StorageEditor : EditorWindow
{
    static private StoreB storage;

    [MenuItem ("Window/Storage Editor")]
    static void Init()
    {
        // Get and show window.
        // Create new component if it does not contain a StoreB.

        ////

        storage.listB.Add( new C() );

        if( storage.listB[ 0 ].GetType() == typeof( C ))
        {
            // this is true
        }
    }
};

How do I maintain the inheritance that exists in the editor?

There is no solution, as far as I know, and I really don’t think that a solution is possible. Essentially, you’re telling Unity “I want to serialize a collection of B”, and then Unity serializes the member fields of B, in the collection. If in the Editor, you add a new instance of C, to your collection B, Unity only will be able to serialize the member fields of C, that are also contained in the base-type of B.

One possible workaround would be to create a new type, which could act as a data transfer object (DTO). One of the fields of your DTO would then be a “type” flag (eg: a string or an enum) indicating which type the DTO should be serialized to. Finally, at run-time, you’d turn your collection of DTOs into instances of A, B, or C, by querying your “type” flag, and instantiating the appropriate type.