Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Correct use of C# 'new' modifier to make protected property public

Tags:

c#

inheritance

Let's say I have an abstract base class:

public abstract class BaseClass
{
    private MyObject myObject;

    protected MyObject PropA
    {
        get
        {
            if(myObject == null) this.myObject = new MyObject();
            return this.myObject;
        }
    }
}

...and that in one of my derived classes, I want to make the protected base class property PropA public. Would it be correct to use the new modifier in this context?

public class DerivedClass : BaseClass
{
    public new MyObject PropA
    {
        get
        {
            return base.PropA;
        }
    }
}
like image 452
MajorInc Avatar asked Nov 01 '14 22:11

MajorInc


2 Answers

Would it be correct use of the new modifier in this context?

Technically - yes, there will no errors or warnings.

As for me, using of new keyword itself as a modifier indicates a design drawback.

I'll give one example.

public class MyList<T> : List<T>
{
    public int AddCallsCount;
    public new void Add(T t)
    {
        AddCallsCount++;
        base.Add(t);
    }
}

[TestClass]
public class Test
{
    [TestMethod]
    public void TestThatsNotGood()
    {
        List<object> list = new MyList<object>();
        list.Add(1);
        list.Add(2);

        MyList<object> myList = list as MyList<object>;

        Assert.AreEqual(0, myList.AddCallsCount);

    }
}

It looks like polymorphism works, but actually does not.

UPDATE: Ok, there is very simplified explanation. I omit explanation of what polymorphism is.

Polymorphims is realized with implementation of abstract\virtual and overriding methods. As soon as neither virtual nor override modifiers are specified MyList<T>.Add is just another 'common' public method. And with MyList<T> inherited List<T>, MyList<T>.Add 'hides' List<T>.Add because name and parameters of both methods are same.

At lower level: as soon as List<T> type definition of method Add isn't marked with virtual keyword, compiler won't search for overriding methods of actual instance type (MyList<T> in this certain case) for variable of given type (List<T> in this certain case).

Definetely it may lead to logic errors and incorrect usage of class API.

Hence, compiler 'thinks' that probably there is a logical mistake or design drawback and warns programmer. The new keyword is just a way to talk to the compiler

yes, I know that it's not good, but I need it because of my bad design

.

like image 179
Valentin P. Avatar answered Nov 10 '22 00:11

Valentin P.


The new keyword works and is correct, if you want to add a member in a derived class that has the same name as a member in the base class; however, it seems that this design defies the purpose of abstract classes. Make PropA public and virtual in the base class or public and abstract:

public abstract class BaseClass
{
    // Property not implemented here.
    public abstract MyObject PropA { get; }

    private MyObject _propB;
    // Property implemented, but implementation can be overridden in derived class.
    public virtual MyObject PropB
    {
        get { return _propB ?? (_propB = new MyObject()); }
    }

    public int PropC { get { return 5; } }
}

public class DerivedClass : BaseClass
{
    // You must provide an implementation here.
    private MyObject _propA;
    public override MyObject PropA
    {
        get { return _propA ?? (_propA = new MyObject()); }
    }

    // You are free to override this property and to provide an new implementation
    // or to do nothing here and to keep the original implementation.
    public override MyObject PropB
    {
        get { return <new implementation...>; }
    }

    // PropC is inherited as is and is publicly visible through DerivedClass as well. 
}
like image 42
Olivier Jacot-Descombes Avatar answered Nov 09 '22 22:11

Olivier Jacot-Descombes