Freigeben über


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

  • Anonymous
    February 06, 2011
    The comment has been removed

  • Anonymous
    February 06, 2011
    The comment has been removed

  • Anonymous
    February 07, 2011
    Oh, and there's static internal extern Bar() {}, of course.

  • Anonymous
    February 07, 2011
    Oh, and there's static internal extern Bar() {}, of course.

  • Anonymous
    February 07, 2011
    @James: I have a class called ExternalInput and I always smirk a little every time I have to type "internal ExternalInput ..."

  • Anonymous
    February 07, 2011
    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.

  • Anonymous
    February 07, 2011
    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...

  • Anonymous
    February 07, 2011
    I used this construct quite a few times when I wanted to ensure that all classes in a hierarchy provide a ToString() implementation.

  • Anonymous
    February 07, 2011
    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.

  • Anonymous
    February 07, 2011
    The comment has been removed

  • Anonymous
    February 07, 2011
    The comment has been removed

  • Anonymous
    February 07, 2011
    The comment has been removed

  • Anonymous
    February 07, 2011
    This is why I read blogs like this. This is why I love programming.

  • Anonymous
    February 07, 2011
    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.

  • Anonymous
    February 07, 2011
    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>

  • Anonymous
    February 07, 2011
    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)

  • Anonymous
    February 08, 2011
    @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.

  • Anonymous
    February 08, 2011
    "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.

  • Anonymous
    February 09, 2011
    I too use this pattern to ensure a meaningful ToString() implementation:    Public MustOverride Overrides Function ToString() As String