Search code examples
c#unity-game-engineinheritanceinstancepass-by-reference

'new' keyword returning the same instance of a class


I have these two classes, one inheriting from the other.

When an external script calls .copy(), it always receives a parent DataComponent, never a BooleanProperty.

If copy() isn't called, a pass-by-reference is obtained instead, causing changes to one instance to affect another one (because they're the same; I don't want this);

I believe this is a me-problem not knowing the syntax of the language or something, hopefully it's just that.

Using Unity 2020.3.17f1 with Windows 10.

Code of the two classes:

[System.Serializable]
public class DataComponent
{
    public DataComponent(string n = "")
    {
        name = n;
    }

    public string name;
    [System.NonSerialized]public string value;

    public DataComponent copy()
    {
        DataComponent ret = new DataComponent(this.name);
        ret.value = this.value;
        return ret;
    }
}

[System.Serializable]
public class BooleanProperty : DataComponent
{
    public BooleanProperty(string n = "") : base(n) { }

    public new bool value;

    public new BooleanProperty copy()
    {
        BooleanProperty ret = new BooleanProperty(name);
        ret.value = value;
        return ret;
    }
}

-The problem was solved by declaring a separate copyBool() method inside BooleanProperty. Calling copyBool() works as expected (returns a new instance)


Solution

  • The use of new like this is a red flag that you're using inheritance incorrectly. You have two classes that need to implement the same functions and be used interchangeably. This sounds like an interface.

    
    public interface IComponent
    {
        IComponent Copy();
    }
    public class DataComponent : IComponent
    {
        public string Value { get; set; } = "";
        public IComponent Copy()
        {
            return new DataComponent { Value = Value };
        }
    }
    public class BooleanComponent : IComponent
    {
        public bool Value { get; set; }
        public IComponent Copy()
        {
            return new BooleanComponent { Value = Value };
        }
    }
    

    If you have other requirements that mean you need to inherit BooleanComponent from DataComponent you could do that, making Copy virtual and still returning an IComponent.