Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does C# support abstract overrides of abstract members?

Tags:

c#

abstract

Whilst browsing through some legacy code, I was surprised to encounter an abstract override of a member that was abstract by itself. Basically, something like this:

public abstract class A
{
    public abstract void DoStuff();    
}

public abstract class B : A
{
    public override abstract void DoStuff();  // <--- Why is this supported?
}

public abstract class C : B
{
    public override void DoStuff() => Console.WriteLine("!");    
}

Isn't the distinction between a virtual or abstract member always available to the compiler? Why does C# support this?

(This question is not a duplicate of What is the use of 'abstract override' in C#? because the DoStuff-method in class A is not virtual but abstract as well.)

like image 678
Rob Wijkstra Avatar asked Sep 13 '17 12:09

Rob Wijkstra


People also ask

Why do we use symbol in C?

The most common use of symbols by programmers is for performing language reflection (particularly for callbacks), and most common indirectly is their use to create object linkages. In the most trivial implementation, they are essentially named integers (e.g. the enumerated type in C).

What does -> mean in C code?

Arrow operator to access the data member of a C Structure We have accessed the values of the data members using arrow operator(->).

Why does C# exist?

C# is a modern object-oriented programming language developed in 2000 by Anders Hejlsberg at Microsoft as a rival to Java (which it is quite similar to). It was created because Sun, (later bought by Oracle) did not want Microsoft to make changes to Java, so Microsoft chose to create their own language instead.

Is C still used in 2022?

C is one of the earliest and most widely used programming languages. C is the fourth most popular programming language in the world as of January 2022. Modern languages such as Go, Swift, Scala, and Python are not as popular as C. Where is C used today?


1 Answers

To clarify the question: the question is not "why is an abstract override legal?" An existing question handles that. (See also my blog post on the subject.)

Rather, the question is "why is an abstract override legal when the overridden method is also abstract?"

There are several arguments in favour of not giving an error here.

  1. It's harmless.

  2. To give an error, someone on the compiler team must have thought of this scenario and considered it to be worth the time to design the feature, verify that it doesn't cause any bad interactions with other features, write a detailed specification, implement it, test it, write the documentation, translate the error message into two dozen languages, translate the documentation, and maintain the feature forever. What's the compelling benefit that justifies those costs? I see none.

  3. Whenever something looks weird in C# ask yourself what if the base class was owned by someone not on my team and they like to edit it?

Consider for example a variation on your scenario:

public abstract class Z 
{
  public abstract void DoStuff();
}

public class A : Z
{
    public override void DoStuff() 
    { 
      throw new NotImplementedException(); 
    }
}

public abstract class B : A
{
    public override abstract void DoStuff();
}

The authors of class A realize that they have made a mistake and A and DoStuff should be abstract. Making a class abstract is a breaking change because anyone who says "new A()" is now wrong, but they verify that none of their client teams in their org have created a new A. Similarly, calling base.DoStuff is now wrong. But again, there are none.

So they change their code to your version of class A. Should class B now have a compile time error? Why? There's nothing wrong with B.

Many features of C# that seem odd are there because the designers consider the brittle base class to be an important scenario.

  1. Finally, we should consider what the preconditions are for overriding a method. The overridden method has to be accessible by the overriding code, the overriding code has to be in a derived type, and the overridden method has to be a virtual method in the first place. There are obvious good reasons for those requirements. Introducing another requirement -- overrides require that no more than one of the overriding and overridden method be abstract -- doesn't have a principled reason underlying it.
like image 152
Eric Lippert Avatar answered Sep 21 '22 07:09

Eric Lippert