Search code examples
c#unity-game-enginepolymorphismsubtyping

Force closes on subtype polymorphic object instantiation


I have the following setup:

public abstract class Parent {
    // logic for class
    public virtual int Value {get;set;}
    public Parent(){}
}

public class Child1 : Parent {
    // child specific logic here
    public Child1 () : base() {
        base.Value = 4;
    }
}

public class Child2 : Parent {
    // child specific logic here
    public Child2 () : base() {
        base.Value = 6;
    }
}

public class RunMe {
    Parent p;

    public Parent instantiateObject(string s) {
        switch(s) {
            case "child1":
                return new Child1();
            break;
            default:
            case "child2":
                return new Child2();
            break;
        }
    }

    public RunMe() {
        p = instantiateObject("child1");
    }
}

when I run code similar to this, Unity force closes. I know C# supports subtype polymorphism, so I'm not really sure why this isn't working. It is nothing special or advanced; so I'm super confused. Shameless admission, I'm in the java camp, and I do (un)consciously try to fit my java paradigm into the C# paradigm. Am I not using it correctly or am I not understanding how sub-typing works in C#?


Solution

  • It appears that using

    base.Value = 4
    

    On an accessor that is defined as virtual inside an abstract class causes problems. As I'm not really comfortable with the more esoteric underpinnings of C# I don't really know or understand why this is the case. But altering the code to look like this works:

    public abstract class Parent {
        // logic for class
        public int Value {get;set;}
        public Parent(){}
    }
    
    public class Child1 : Parent {
        // child specific logic here
        public Child1 () : base() {
            base.Value = 4;
        }
    }
    
    public class Child2 : Parent {
        // child specific logic here
        public Child2 () : base() {
            base.Value = 6;
        }
    }
    
    public class RunMe {
        Parent p;
    
        public Parent instantiateObject(string s) {
            switch(s) {
                case "child1":
                    return new Child1();
                break;
                default:
                case "child2":
                    return new Child2();
                break;
            }
        }
    
        public RunMe() {
            p = instantiateObject("child1");
        }
    }
    

    Notice I removed the virtual keyword from my accessor in my abstract class Parent