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.

Comments (19)

  1. Anthony P says:

    That sort of goes in line with a simple class declaration that is unintuitive (to me, at least), yet is certainly perfectly valid code, and I suppose it is useful. And that, of course, it just the simple example of class A, abstract class B : A.

  2. James Hart says:

    Wonder what other valid oxymoronic declarations C# supports. One I've noticed before is static dynamic Foo() {}…

  3. James Hart says:

    Oh, and there's static internal extern Bar() {}, of course.

  4. James Hart says:

    Oh, and there's static internal extern Bar() {}, of course.

  5. Stuart says:

    @James: I have a class called ExternalInput and I always smirk a little every time I have to type "internal ExternalInput …"

  6. I don't even think it's a strange construct, to be honest. I treat "override" in those method declarations as a noun – as in, "a method override". On the other hand, "abstract" is definitely an adjective. So "abstract override" is an override that is abstract. Makes sense.

  7. Stuart says:

    Another one that's odd at first glance is putting internal or public members on a private type (which could be to implement a public interface, for consumption by an API that accesses public properties by reflection (like DataBinder.Eval in ASP.NET) or because to access members of a private type from within the containing type those members *must* be at least internal…

  8. Daniel Grunwald says:

    I used this construct quite a few times when I wanted to ensure that all classes in a hierarchy provide a ToString() implementation.

  9. JBSnorro says:

    To continue the list of valid oxymoronic C# statements: "this = new SomeValueType();".

    Or the nullref exception from "new SomeType?().GetType();"

    Or "new SomeType() == null" can evaluate to true, by overriding the equality-operator or via the ProxyAttribute.

  10. Simon Buchan says:

    My C++ fu might not be up to snuff, but this looks like the exact opposite behavior to C++, where you can define a method as abstract (pure virtual, "= 0") and give it a body (though only separately to the declaration) – which means "'Unimplemented', but callable (e.g. by subtypes)", as opposed to C#'s "Implemented, but not by subtypes". I would assume the CLR allows "base.Name", but does C#?

  11. FedeAzzato says:

    How about "partial sealed class Foo { }"? That would be odd!

    That was a tricky question. In fact I just checked it, and the partial modifier in this case can only appear before the class keyword, which makes a lot of sense.

  12. Daniel Brückner says:

    I – for whatever reasons – like protected sealed override Foo Bar { … }.

  13. Anon says:

    This is why I read blogs like this.

    This is why I love programming.

  14. Bas Mommenhof says:

    How about "public MyFrob Frobber { get; private set; }"

    For which ghostdoc creates the summary "Gets or sets the frobber".

    Except for the code in the class itself and its nested types any other

    code using this class will get a ReadOnly exception.

    In which case the programmer will curse the documentation for being wrong.

    There is no way for Ghostdoc to do it right because what is private for some is public for others.

  15. Kyle Lahnakoski says:

    I will try that today!  I thought the pattern was supposed to be:

    <code>

    abstract class FrobThingy : Thingy {

    public abstract override string Name {

    get{

    throw NotImplementedExcetion();

    }

    }

    }

    </code>

  16. Ian Ringrose says:

    The other case I have seen this is when you wish to make the subclass author decide if the default implementation is valid for them, but you still wish to provide a default implementation, so you have an abstract method with a body.  When this happens below the “root” you get an “abstract override” method.   (For some reason I saw this a lot in C++ code bases I worked on)

  17. Anthony P says:

    @Kyle, @Ian, unlike abstract classes, which can in fact be fully implemented yet marked abstract, you cannot have a body for methods marked abstract. @Kyle, the pattern you might be remembering would be for interface implementation, where methods would be given such bodies automatically by the IDE or, of course, manually by the programmer.

  18. pete.d says:

    "There is no way for Ghostdoc to do it right because what is private for some is public for others."

    Well, one "fix" is to assume XML docs are for public API only. Then Ghostdoc could produce a default doc tailored only to the public members.

    I know I'm not the only one who often doesn't bother to put XML docs on non-public members.

  19. S says:

    I too use this pattern to ensure a meaningful ToString() implementation:

       Public MustOverride Overrides Function ToString() As String