liamlim
liamlim

Reputation: 31

Is it possible to use both 'new' and 'override' in a definition of property?

I tried to solve inheritance problem in my application. It's basically something like this:

interface IAbcBase
{
    int? Value { get; }
}

interface IAbc : IAbcBase
{
    new int Value { get; }
}

class BaseA : IAbcBase
{
    public virtual int? Value => (this as A)?.Value;
}

class A : BaseA, IAbc
{
    // public override int? Value => 4;     // line A
    public new int Value => 4;              // line B
}

I want to hide property Value from BaseA and replace it by non nullable property on A. But at the same time I also want to be able to override property Value to provide more effective definition for Value in case I assign it to variable of type BaseA.

BaseA a = new A();
var b = a.Value; // b is int? which is fine. But ineffective definition was used instead of line A

Is it possible to somehow override property and also hide it at same time (ie uncomment both lines A and B)? In my real application the definition on base class is not that simple and I would love to provide much more effective definition and also hide that Value.

Solution could be to not hide member from base and instead use another name. For example ValueNotNull and mark overriden method as obsolete. It's not that simple though because I can't modify members from interfaces IAbcBase and IAbc. I don't like this solution because then the implementation of IAbc must be explicit so I can override member from BaseA and then I am not able to use name Value on A which is what I want because it's basically non nullable equivalent of Value on BaseA.

I hope I described my issue well. In case any details are needed, I will edit

/// Edit: I was asked to provide examples of use cases if both definitions on line A and line B were allowed. In my real application, I have following definitions (simplified):

    internal sealed class StandardDefinition : Definition
    {
        public Definition Previous { get; }

        public new int NodesCount { get; } 
    }

    internal sealed class RootDefinition : Definition
    {
    }

    internal abstract class Definition
    {
        public int? NodesCount => (this as StandardDefinition)?.NodesCount;
    }

Root node is basically start position for chess analysis which is not necessarily standard start position. NodesCount is number of nodes which were used for analysing this move. It's something I don't have for root position because I never get start position as a result from any analysis so there is nothing to return (there is much more properties like that, I simplified a lot).

I use mainly variables of Definition except one place in code right after analysis is done and I get StandardDefinition. Thus mostly ineffective definitions for NodesCount and other similar properties are used instead of using definition from StandardDefinition. That's why I want to be able to override, because most instances are obviously of type StandardDefinition. There is only few RootDefinitions. Most of that casting and testing for null is absolutely unnecessary. After I analyse position, I get StandardDefinition and now I would like to be able to hide old definition which is nullable and provide definition which just returns nonnulable nodes count used for analysing this position. Again to avoid all unnecessary casting, etc.

Upvotes: 1

Views: 96

Answers (1)

Marc Gravell
Marc Gravell

Reputation: 1064004

No, basically, if you mean the public API on A. The only solution to this is to introduce an extra layer:

abstract class AlmostA : BaseA
{
    public override int? Value => GetValue();
    protected int GetValue() => 4;
}
class A : AlmostA, IAbc
{
    public new int Value => GetValue();
}

If you only mean for the purposes of satisfying the IAbc interface, then "explicit interface implementation" is your friend:

class A : BaseA, IAbc
{
    private int GetValue() => 4;
    public override int? Value => GetValue();
    int IAbc.Value => GetValue();
}

Upvotes: 1

Related Questions