Okay, two alternatives, but before I begin, you need to know this:
public abstract class GatewayBase { ... }
public class Gateway : GatewayBase { ... }
Alternative #1
public abstract class ModelBase
{
public GatewayBase GatewayBase { get; private set; } // property named GatewayBase
public ModelBase(GatewayBase gateway)
{
GatewayBase = gateway;
}
}
public class Model : ModelBase
{
public Gateway Gateway { get; private set; } // property named Gateway
public Model(Gateway gateway)
: base(gateway)
{
Gateway = gateway;
}
}
Alternative #2
public abstract class ModelBase
{
public GatewayBase Gateway { get; private set; } // property named Gateway
public ModelBase(GatewayBase gateway)
{
Gateway = gateway;
}
}
public class Model : ModelBase
{
public new Gateway Gateway { get; private set; } // property named Gateway plus "new" modifier
public Model(Gateway gateway)
: base(gateway)
{
Gateway = gateway;
}
}
Discussion:
With Alternative #1, the concrete class Model can “see” two versions of Gateway. One is called GatewayBase and the other is called just Gateway, but they both contain the exact same instance. With Alternative #2, technically, there are still two versions of Gateway but one hides the other, so there is effectively only one (unless you bypass it using base.Gateway). I like that Alternative #2 lets me call the property Gateway wherever I am, because it gets used a lot in both the base and concrete classes and it’s a short but clear name. Still, I have some hesitation about using the new modifier in this way. Is this really a legitimate scenario for hiding a property?
Which would you choose and why?
Or feel free to suggest other alternatives.
Thanks.
EDIT:
I should mention that GatewayBase and ModelBase are in a dependent assembly, so they don’t know anything about Gateway and Model. However, Gateway and Model of course know about GatewayBase and ModelBase.
Option 2 looks cleaner, but don’t make a separate backing property, wrap the existing base class’ property by casting it up from GatewayBase to Gateway. This way you won’t have ambiguities about the Gateway used: it’s always the same, just from a different perspective:
You can also use generics to keep things a little more flexible for different types of gateways (a bit like IEnumerable<T>). The problem with generics is that you can’t cast one C<X> to another C<Y> (well, you can, sometimes, in 4.0). The cleanest way to solve that, is to introduce a non-generic interface, which you implement explicitly on your generic class. This way, it’s hidden from view when you’re talking to generic instances, but you can still mix your C<X>’s and C<Y>’s.