Strange but legal

“Can a property or method really be marked as both abstract and override?” one of my coworkers just asked me. My initial gut response was “of course not!” but as it turns out, the Roslyn codebase itself has a property getter marked as both abstract and override. (Which is why they were asking in the first place.)

I thought about it a bit more and reconsidered. This pattern is quite rare, but it is perfectly legal and even sensible. The way it came about in our codebase is that we have a large, very complex type hierarchy used to represent many different concepts in the compiler. Let’s call it “Thingy”:

abstract class Thingy 
{
  public virtual string Name { get { return ""; } } 
  ...

There are going to be a lot of subtypes of Thingy, and almost all of them will have an empty string for their name. Or null, or whatever; the point is not what exactly the value is, but rather that there is a sensible default name for almost everything in this enormous type hierarchy.

However, there is another abstract kind of Thingy, a FrobThingy, which always has a non-empty name. In order to prevent derived classes of FrobThingy from accidentally using the default implementation from the base class, we said:

abstract class FrobThingy : Thingy 
{   
  public abstract override string Name { get; } }
  ...

Now if you make a derived class BigFrobThingy, you know that you have to provide an implementation of Name for it because it will not compile if you don’t.

1 thought on “Strange but legal

  1. It’s interesting that case is legal, but a few other useful ones aren’t:

    1. Have in type `BaseFoo` an virtual method whose implementation is callable on instances of `BaseFoo`, but cannot be inherited. For example, a `BaseFoo` may have a `Clone` method not based on `MemberwiseClone` and always returns a `BaseFoo` instance; any legitimate derived type would need to override that to return a `DerivedFoo` instance. This can be fudged with a runtime check by having the method throw an exception if invoked from the wrong type, but that’s icky.

    2. Have a `BaseFoo` constructor which is usable for constructing `BaseFoo` instances, but cannot be used to construct instances of derived types. This would be especially useful in cases where a type should be publicly constructable, but no derived types should exist outside the control of its assembly. This can be somewhat fudged with a runtime check, but that doesn’t prevent the definition of derived types; since there are ways of constructing and acquiring instances of derived types that don’t go through the base type constructor (e.g. have a derive type’s constructor-chaining instruction throw an exception, and use the derived type’s finalizer to grab a reference) it may be difficult to guard against the creation of “illegitimate” derived-type instances.

    3. Have a class override and shadow the same member. This would allow ToyotaCarFactory override CarFactory.Build() [which returns `Car`] but also shadow it with ToyotaCarFactrory.Build (which returns ToyotaCar). It would also allow a method to be chained in inside-out fashion in cases where a base-class object needs to wrap derived-class method in a lock, try/finally clause, or other such construct.

    I think those are mostly .NET limitations rather than C# (though in the case where a shadowed method’s return type would change I think .NET would make it possible for a class to have both the override and the shadow, with the shadow marked to hide the override from derived classes). Is my understanding correct?

Leave a comment