Reputation: 31
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 RootDefinition
s. 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
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