What Is the Use of 'Abstract Override' in C#

What is the use of 'abstract override' in C#?

There's a useful example for this on Microsoft Docs - basically you can force a derived class to provide a new implementation for a method.

public class D
{
public virtual void DoWork(int i)
{
// Original implementation.
}
}

public abstract class E : D
{
public abstract override void DoWork(int i);
}

public class F : E
{
public override void DoWork(int i)
{
// New implementation.
}
}

If a virtual method is declared abstract, it is still virtual to any
class inheriting from the abstract class. A class inheriting an
abstract method cannot access the original implementation of the
method
—in the previous example, DoWork on class F cannot call DoWork
on class D. In this way, an abstract class can force derived classes
to provide new method implementations for virtual methods
.

Why is it required to have override keyword in front of abstract methods when we implement them in a child class?

When we create a class that inherits from an abstract class and when we implement the inherited abstract class why do we have to use the override keyword?

"Why?" questions like this can be hard to answer because they are vague. I'm going to assume that your question is "what arguments could be made during language design to argue for the position that the override keyword is required?"

Let's start by taking a step back. In some languages, say, Java, methods are virtual by default and overridden automatically. The designers of C# were aware of this and considered it to be a minor flaw in Java. C# is not "Java with the stupid parts taken out" as some have said, but the designers of C# were keen to learn from the problematic design points of C, C++ and Java, and not replicate them in C#.

The C# designers considered overriding to be a possible source of bugs; after all, it is a way to change the behaviour of existing, tested code, and that is dangerous. Overriding is not something that should be done casually or by accident; it should be designed by someone thinking hard about it. That's why methods are not virtual by default, and why you are required to say that you are overriding a method.

That's the basic reasoning. We can now go into some more advanced reasoning.

StriplingWarrior's answer gives a good first cut at making a more advanced argument. The author of the derived class may be uninformed about the base class, may be intending to make a new method, and we should not allow the user to override by mistake.

Though this point is reasonable, there are a number of counterarguments, such as:

  • The author of a derived class has a responsibility to know everything about the base class! They are re-using that code, and they should do the due diligence to understand that code thoroughly before re-using it.
  • In your particular scenario the virtual method is abstract; it would be an error to not override it, and so it is unlikely that the author would be creating an implementation by accident.

Let's then make an even more advanced argument on this point. Under what circumstances can the author of a derived class be excused for not knowing what the base class does? Well, consider this scenario:

  • The base class author makes an abstract base class B.
  • The derived class author, on a different team, makes a derived class D with method M.
  • The base class author realizes that teams which extend base class B will always need to supply a method M, so the base class author adds abstract method M.
  • When class D is recompiled, what happens?

What we want to happen is the author of D is informed that something relevant has changed. The relevant thing that has changed is that M is now a requirement and that their implementation must be overloaded. D.M might need to change its behaviour once we know that it could be called from the base class. The correct thing to do is not to silently say "oh, D.M exists and extends B.M". The correct thing for the compiler to do is fail, and say "hey, author of D, check out this assumption of yours which is no longer valid and fix your code if necessary".

In your example, suppose the override was optional on SayHello because it is overriding an abstract method. There are two possibilities: (1) the author of the code intends to override an abstract method, or (2) the overriding method is overriding by accident because someone else changed the base class, and the code is now wrong in some subtle way. We cannot tell these possibilities apart if override is optional.

But if override is required then we can tell apart three scenarios. If there is a possible mistake in the code then override is missing. If it is intentionally overriding then override is present. And if it is intentionally not overriding then new is present. C#'s design enables us to make these subtle distinctions.

Remember compiler error reporting requires reading the mind of the developer; the compiler must deduce from wrong code what correct code the author likely had in mind, and give an error that points them in the correct direction. The more clues we can make the developer leave in the code about what they were thinking, the better a job the compiler can do in reporting errors and therefore the faster you can find and fix your bugs.

But more generally, C# was designed for a world in which code changes. A great many features of C# which appear "odd" are in fact there because they inform the developer when an assumption that used to be valid has become invalid because a base class changed. This class of bugs is called "brittle base class failures", and C# has a number of interesting mitigations for this failure class.

What is the use of 'abstract override' in C#?

There's a useful example for this on Microsoft Docs - basically you can force a derived class to provide a new implementation for a method.

public class D
{
public virtual void DoWork(int i)
{
// Original implementation.
}
}

public abstract class E : D
{
public abstract override void DoWork(int i);
}

public class F : E
{
public override void DoWork(int i)
{
// New implementation.
}
}

If a virtual method is declared abstract, it is still virtual to any
class inheriting from the abstract class. A class inheriting an
abstract method cannot access the original implementation of the
method
—in the previous example, DoWork on class F cannot call DoWork
on class D. In this way, an abstract class can force derived classes
to provide new method implementations for virtual methods
.

Why can I abstract override an abstract method?

Why can I abstract override an abstract method?

For starters, there's no practical reason for preventing it. If it produced a compiler error, all that would do is make classes more brittle. For example:

abstract class Foo
{
virtual void DoSomeStuff()
{
//Do Some Stuff
}
}

abstract class Bar : Foo
{
abstract override void DoSomeStuff();
}

If abstract override on abstract was illegal, changing DoSomeStuff on Foo to abstract would now prevent Bar from compiling. The abstract override is redundant, but there's no potential negative side effects, so the compiler is okay with this.


Why isn't there a compiler warning informing me that what I've wrote does nothing?

The compiler produces warnings for certain things that represent risk: non-explicit method hiding, unreachable code, using obsolete methods, etc. The only "problem" an unnecessary abstract override could indicate is that the code was not efficiently written. That's not something the compiler cares about.


Is there some use case where abstract override on an abstract does something useful?

Not functionally. However, there are a few use cases where you might intentionally do so:

  • To improve the "readability" of the code. Having the redundant abstract override would serve as a reminder that the method is abstract.
  • If future changes to the base class include providing a virtual implementation, you can preemptively prevent some classes from accessing that base class.
  • If the abstract override is redundant because the base class was changed from a virtual implementation to abstract, it can safely be left alone.

Override abstract method, but keep method abstract?

In this case, I think it would be better to divide your logic into 2 methods, one method you play with and the other method your users play with. Assuming the "CreateCustomColumns" method is the name you want your users to override, you create another method, say "CreateCustomColumnsCore", for yourself. The classes may look like this:

public abstract class ComponentController
{
protected abstract void CreateCustomColumnsCore();
}

public abstract class ClientComponentController : ComponentController
{
protected override void CreateCustomColumnsCore()
{
// your code here

CreateCustomColumns(); // call users' implementation
}

public abstract void CreateCustomColumns();
}

public class ClientInvoicesComponentController: ClientComponentController
{
public override void CreateCustomColumns()
{
// user must implement this method.
}
}

Users can still override your CreateCustomColumnsCore method, this could be a feature or a bug based on if you can permit users to do this.

C# Override an abstract class' function with a different one with a Class Type return type

This can be produced with NVI pattern:

public abstract class DayInfo
{
protected virtual void GetInfoCore() {
throw new NotImplementedException();
}

// or
// protected abstract void GetInfoCore();

public void GetInfo() {
GetInfoCore();
}
}

public class DayInfo<T> : DayInfo
{
private T info;

public DayInfo(T data) {
info = data;
}

public new T GetInfo() { // << This
return info;
}

protected override void GetInfoCore() {
GetInfo();
}
}

Why must an abstract method be protected in a derived class?

I don't believe this is possible due to how inheritance works. All children (derived classes) have everything a parent has, plus whatever extra stuff you need.

That said - if you want a child class to NOT have one of the methods its parent has, you can do it with interfaces. Simply define an interface which lacks the one method you want to restrict, and have both parent and child implement it.



Related Topics



Leave a reply



Submit