Strange, but legal

Strange, but legal

Rate This
  • Comments 19

"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.

  • 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.

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

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

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

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

  • 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.

  • 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...

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

  • 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.

  • 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#?

  • 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.

  • I - for whatever reasons - like protected sealed override Foo Bar { ... }.

  • This is why I read blogs like this.

    This is why I love programming.

  • 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.

  • 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>

Page 1 of 2 (19 items) 12