When calling methods on a base class from a derived class, should the 'base' keyword be used? It seems using the base keyword would increase code readability but for me so far, when I exclude it, there is no affect on code compilation and execution.
The base keyword is important when overriding methods:
override void Foo()
{
base.Foo();
// other stuff
}
I never use it for anything else.
You should not use base unless you specifically mean "Even if there is a method in this class that overrides the base implementation, I want to call the base implementation and ignore the one on this class".
Using base bypasses the virtual dispatch mechanism that is so important in polymorphism by causing a call instruction to be emitted rather than callvirt.
So saying base.Foo() is very, very different in semantics to saying this.Foo(). And you almost always want the latter.
It does matter if you have overridden a method:
class Test {
public override string ToString() { return "Hello World"; }
public string M1() { return ToString(); } // Test.ToString
public string M2() { return base.ToString(); } // System.Object.ToString
static void Main() {
var t = new Test();
Console.WriteLine("M1: {0}", M1()); // Hello World
Console.WriteLine("M2: {0}", M2()); // Test
}
}
Sometimes, you can't avoid it. If your class overrides an implementation of a function from the base class, then without the base keyword, calls could be dispatched to the implementation in your class.
In all other situations, it's a matter of style (much like "Should I prefix all calls/field accesses with this). I say "No" as it tends to increase code clutter without significantly helping readability, but "Yes" is just as valid an answer - especially if you have a class with many overridden methods, but will be including many calls upwards in the hierarchy.
I'd say no. The main purpose of base is to allow you to call base class versions of virtual methods without virtual dispatch taking place. Personally, I consider any other use of base to be an abuse - it doesn't really buy you anything over just calling a method as usual (or using this), and it will break if you later override the called method in your class.
Also, there is a very real difference if the method is virtual, and someone down the line overrides it. To give an example, say you write this (in a reusable class):
class Base {
public virtual void Foo() {}
}
class Derived : Base {
void Bar() { base.Foo(); }
}
And later on someone else who uses your class writes:
class MoreDerived : Derived {
public override void Foo() {}
}
Now your base.Foo() will not do dynamic dispatch, and therefore will not call the overridden Foo() in MoreDerived. It may be what you actually want, but I'd find such a code very suspect if that was the intent.
There are times when the base keyword has to be used such when you want to call a method in the base class that's been overidden in the derived class.
Look to this example:
class ParentClass {
public virtual void A() {
// Some operations
}
}
class ChildClass : ParentClass {
public override void A()
{
base.A();
}
}
If we execute ChildClass.A() then we have some operations, but in this case:
class ParentClass {
public virtual void A() {
Console.WriteLine("ParentClass.A");
}
}
class ChildClass : ParentClass {
public override void A()
{
A();
}
}
we have StackOverflowException, because ChildClass.A() execute ChildClass.A()
There will be no difference in the generated IL in most cases.
However, if you are overriding a virtual method in the base class, or hiding a method in the base class using the "new" keyword, then this is required, and will change the meaning, since it explicitly calls the base class method.
However, it is often a good idea, since it improves readability, and hence maintainability. If you are explicitly wanting to call a method in the base class, then I feel that it's a good idea, even when not technically required.
Related
I would like to obligate all the sub classes of my class to override a method, but I want to give a basic implementation to this method.
I know its sounds a bit weird so here is an explanation:
I have a big code base (C#) which make use of an abstract method. each sub class overrides this method and has its own special needs from this method.
What I did until now was to add an explicit method with a partial implementation in the base class, and I am overriding the abstract method and calling the explicit one in all the sub classes. This way I can avoid duplicate code and still maintain each subclass "special needs".
This solution seems to me pretty messy.
Can someone introduce me to a better solution?
an abstract example:
class base{
method abstract count()
}
class A:base{
method override count(){
count()
print('A')
}
}
class B:base{
method override count(){
count()
print('B')
}
}
Call base.count() to invoke the base class's count method.
Edit: I re-read your solution and now I'm not sure if you're already doing this. Maybe decompose the method into several different methods, some of which can be overridden. E.g count() => countApples() + countOranges() - wormMultiplier() *countWorms();
Here's how I would do it:
Create a public method called Count in the BaseClass.
Have that method call the base count implementation method,
and than the abstract count method.
mark the abstract count method protected.
This way, everyone that's inheriting the Base class is forced to add it's own implementation, while anyone that's using it must go through the public Count class that's also executing the base implementation.
Here's the basic structure of the code:
abstract class Base
{
public void Count()
{
CountBaseImplementation();
CountSubClassesImplementation();
}
private CountBaseImplementation()
{
// Base implementation here
}
protected abstract CountSubClassesImplementation();
}
class A : Base
{
protected override CountSubClassesImplementation()
{
// A specific implementation here
}
}
class B : Base
{
protected override CountSubClassesImplementation()
{
// B specific implementation here
}
}
Consider the code:
class ChildClass : BaseClass {
public void Method1() {} //some other method
}
abstract class BaseClass : IChildInterface {
public
virtual //<- If we add virtual so that this method can be overridden by ChildClass, we get StackOverflowException and DoWork() implementation in IChildInterface is never called.
void DoWork() {
//base class specific implmentation
((IChildInterface)this).DoWork(); //call into default implementation provided by IChildInterface
}
}
interface IChildInterface : IBaseInterface {
void IBaseInterface.DoWork() {
//implmentation
}
}
interface IBaseInterface {
void DoWork();
}
The problem is that if we mark DoWork() in BaseClass as virtual so that it can be overridden by child classes, it prevents it from calling into IChildInterface's default implementation of DoWork(), causing StackOverflowException.
If we remove virtual modifier from DoWork() in the BaseClass, everything works and the IChildInterface's default implementation of DoWork() is called.
Is such a behavior a bug, or by design?
Is there a way to make it possible for some child classes provide their own implementation of DoWork() (thus overriding BaseClass's implementation) but still being able to use IChildInterface's default implementation of DoWork()?
You're calling BaseClass.DoWork recursively which, if you're lucky, will result in a StackOverflowException. If the call was the last one in the method, you'd get an infinite recursion due to tail call optimizations. You'd end up with a core stuck at 100% until you killed the app.
This code :
public virtual void DoWork() {
((IChildInterface)this).DoWork(); by IChildInterface
}
Is identical to :
//That's the actual implementation of the interface method
public virtual void DoWork() {
DoWork();
}
The virtual keyword doesn't matter. You'd still get infinite recursion without it. Whether it exists or not, this line throws a StackOverflowException after a while :
new ChildClass().DoWork();
When you implemented BaseClass.DoWork that became the single implementation available to everyone, unless overridden by a child class.
Interfaces are not abstract classes, even in C# 8. A default method implementation is not an actual method. As the name says, it's a default implementation. It's used when there's no better implementation available. You can't call the default implementation when the method is already implemented in a class.
In fact, in almost every case you wouldn't expect the default method to be called. DIMs are called explicitly through the interface, the same way explicit interface implementations are used. Callers of the method expect the most-derived implementation to run, not the base or mid-level one.
Besides, even on previous C# versions you wouldn't expect casting to an interface to change which method is actually called. You'd expect that only with classes. To call a base class implementation you'd use the base keyword. The base class of BaseClass though is Object which doesn't have a DoWork method.
If you used :
void DoWork() {
base.DoWork();
}
You'd get a CS0117: 'object' does not contain a definition for 'DoWork'
Update
The C# design team has already though about this. This couldn't be implemented efficiently without runtime support and was cut i May 2019. Runtime optimizations is what makes DIM calls as cheap as other calls, without boxing etc.
The proposed syntax is a base(IMyInterface) call :
interface I1
{
void M(int) { }
}
interface I2
{
void M(short) { }
}
interface I3
{
override void I1.M(int) { }
}
interface I4 : I3
{
void M2()
{
base(I3).M(0) // What does this do?
}
}
As all methods inside interfaces are virtual by default the DoWork is virtual inside every each of these definitions/implementations you provided except the ChildClass. When you explicitly use DoWork of IChildInterface it uses BaseClass.DoWork implicitly which then uses ((IChildInterface)this).DoWork(); explicitly again. And so on. You have this loop that is never ending, hence you're getting the StackOverflow.
For the sake of future readers...
While the accepted answer provided by #Panagiotis is correct, in that there is no difference whether virtual modifier is present or not and StackOverflowExcpetion will occur in any case, I wanted to provide a concrete answer to the question that I settled on.
The whole point of implementing DoWork() in the IChildInterface as opposed to in a class was for code reuse and staying "DRY". Classes that implement IChildInterface should however be able to add their own functionality on top of what's provided by IChildInterface.
And therein lies a problem, as calling ((IChildInterface)this).DoWork(); from any class (abstract or not) that implements IChildInterface will result in infinite recursion. The only reasonable way out seems to use protected static members (as in fact is suggested in the Microsoft Docs):
class ChildClass : BaseClass {
public void Method1() {} //some other method
}
abstract class BaseClass : IChildInterface {
public virtual void DoWork() {
// Base class specific implementation here
// Then call into default implementation provided by IChildInterface:
// Instead of this: ((IChildInterface)this).DoWork();
// Use static implementation:
IChildInterface.DoWork(this);
}
}
interface IChildInterface : IBaseInterface {
protected static void DoWork(IChildInterface it){
// Implementation that works on instance 'it'
}
void IBaseInterface.DoWork() => IChildInterface.DoWork(this);
}
interface IBaseInterface {
void DoWork();
}
In the above solution we are staying "DRY" by still having a single (core) implementation of DoWork(), but it is located in a protected static member of the interface IChildInterface instead of being part of its inheritance hierarchy.
Then, as far as the inheritance hierarchy is concerned, all interfaces / classes deriving from / implementing IChildInterface could simply use IChildInterface.DoWork(this) to access the default implementation. This applies to the IChildInterface itself.
Why shall we use sealed keyword on a method or property whenever the current class once inherited from a super class? Suppose we made a class and tend to expose one or more of its methods to the object user but not letting it being inherited at all and use sealed to solve the issue. Then, why not? And what's the reason behind sealing just a current-inherited class's methods or properties?
As stated in the MSDN Docments on sealed:
You can also use the sealed modifier on a method or property that
overrides a virtual method or property in a base class. This enables
you to allow classes to derive from your class and prevent them from
overriding specific virtual methods or properties.
In other words, you can stop the overriding from happening further down the class inheritance hierarchy. As a programmer, you are basically saying that this particular method should have common functionality with all subclasses.
Here's a great code example from the same article:
class X
{
protected virtual void F() { Console.WriteLine("X.F"); }
protected virtual void F2() { Console.WriteLine("X.F2"); }
}
class Y : X
{
sealed protected override void F() { Console.WriteLine("Y.F"); }
protected override void F2() { Console.WriteLine("Y.F2"); }
}
class Z : Y
{
// Attempting to override F causes compiler error CS0239.
// protected override void F() { Console.WriteLine("C.F"); }
// Overriding F2 is allowed.
protected override void F2() { Console.WriteLine("Z.F2"); }
}
UPDATE Per Request For Additional Clarification
Here's a less abstract example of a possible application for a sealed method.
abstract class Car
{
public abstract void Make();
}
class Ford : Car
{
// We don't want someone inheriting from this class to change the
// 'Make' functionality - so we seal the method from being further
// overridden down the inheritance hierarchy
sealed public override void Make() { Console.WriteLine("Ford"); }
}
// This way there is no way (besides shadowing) someone inheriting from Ford
// can change the behavior of Make() - so these two types will contain the
// same behavior. Pretty nice, eh!?
class Focus : Ford
{
}
class Escape : Ford
{
}
There are 2 primary reasons for sealing a class or a method.
The first, and the most important one (probably) is that you disallow inheritance on the type or method in question. This can be important in some cases.
The second reason is that the compiler can apply optimizations it otherwise could not have done.
Doing a virtual method lookup is not a very costly affair, but it does incur some overhead. If the compiler knows that:
You're using the most specific class you can in the given situation
The given type or method is sealed
then in some cases it can compile a call to a method into a direct call to the correct method, and not a lookup through the virtual method table of the type. This will remove the overhead of the virtual method lookup in this situation.
As stated in the docs ( http://msdn.microsoft.com/en-us/library/88c54tsw.aspx ) this prevents a method from being virtual. It is useful because override keyword implies virtual. If you want to override a method but stop further overriding you can add sealed to the method definition.
If the class itself is sealed there is no reason to seal a specific method since the class cannot be inherited anyway.
You apply sealed to an overridden method (or property etc.) to disallow classes that derive from your class, overriding that method further.
If I have two classes that both implement an interface, but also inherit, do I need to make the function virtual? eg given:
interface IDoSomething
{
void DoSomething();
}
class A : IDoSomething
{
public void DoSomething()
{
//do A
}
}
class B : A
{
public new void DoSomething()
{
//do B
}
}
Would the following code do A or B?
IDoSomething doer = new B();
doer.DoSomething(); //do A or do B?
I'm getting confused because I'm under the impression that all inteface calls are effectively virtual, but obviously I am using the new operator to hide the base definition.
Here is the explanation. Already available at stackoverflow forums.
Quoting Jeffrey Ritcher from CLR via CSharp 3rd Edition here
The CLR requires that interface methods be marked as virtual. If you
do not explicitly mark the method as virtual in your source code, the
compiler marks the method as virtual and sealed; this prevents a
derived class from overriding the interface method. If you explicitly
mark the method as virtual, the compiler marks the method as virtual
(and leaves it unsealed); this allows a derived class to override the
interface method. If an interface method is sealed, a derived class
cannot override the method. However, a derived class can re-inherit
the same interface and can provide its own implementation for the
interface’s methods.
class A : IDoSomething
{
public virtual void DoSomething()
{
//do A
}
}
class B : A
{
public override void DoSomething()
{
//do B
}
}
I prefer leppie's solution. If that's not an option:
class A : IDoSomething
{
void IDoSomething.DoSomething()
{
//do A
}
}
class B : A
{
void IDoSomething.DoSomething()
{
//do B
}
}
But note that this will hide the implementation, so you can't do ((A)doer).DoSomething().
If you can't change class A to either of these solutions, I don't think there's a sure way to override it in all cases. You could both explicitly implement the interface and make a public new method on B. That way if it's statically known as an IDoSomething or as a B it will use B's implementation, but if it's known as an A it will still use A's implementation.
Although C# and .net allow derived classes to re-implement interface methods, it is often better to have the base class use a virtual method to implement the interface, and have the derived class override that method, in any situation where a derived class might wish to augment, rather than entirely replace, the base-class implementation. In some languages like vb.net, this can be done directly regardless of whether a class exposes a public member with the same name and signature as the interface member being implemented. In other languages like C#, a public method which implements an interface can be marked unsealed and virtual (allowing a derived class to override it and have that override call base.Member(params) but an explicit interface implementation cannot. In such languages, the best one can do is something like:
class MyClass : MyInterface
{
void MyInterface.DoSomething(int param)
{
doSomething(param);
}
protected virtual void doSomething(int param)
{
...
}
}
class MyClass2 : MyClass
{
protected override void doSomething(int param)
{
...
base.doSomething(param);
...
}
}
In some cases, having the interface implementation wrap a virtual call can be advantageous, since it allows the base class to ensure that certain things happen before or after the overridden function. For example, a non-virtual interface implementation of Dispose could wrap a virtual Dispose method:
int DisposingFlag; // System.Boolean doesn't work with Interlocked.Exchange
void IDisposable.Dispose()
{
if (Threading.Interlocked.CompareExchange(DisposingFlag, 1, 0) == 0)
{
Dispose(true);
DisposingFlag = 2;
Threading.Thread.MemoryBarrier();
GC.SuppressFinalize(this);
}
}
public bool Disposed { get {return (DisposingFlag != 0);} }
public bool FullyDisposed { get {return (DisposingFlag > 1);} }
This will (unlike Microsoft's default wrapper) ensure that Dispose only gets called once, even if multiple threads try to call it simultaneously. Further, it makes a Disposed property available. Using Microsoft's wrapper, every derived class that wants a Disposed flag would have to define its own; even if the base-class Disposed flag were protected or public, it wouldn't be safe to use because it wouldn't get set until after derived classes had already begun cleanup. Setting DisposingFlag within the wrapper avoids that problem.
I have a class that is generated by some tool, therefore I can't change it. The generated class is very simple (no interface, no virtual methods):
class GeneratedFoo
{
public void Write(string p) { /* do something */ }
}
In the C# project, we want to provide a way so that we can plug in a different implementation of MyFoo. So I'm thinking to make MyFoo derived from GeneratedFoo
class MyFoo : GeneratedFoo
{
public new void Write(string p) { /* do different things */ }
}
Then I have a CreateFoo method that will either return an instance of GeneratedFoo or MyFoo class. However it always calls the method in GeneratedFoo.
GeneratedFoo foo = CreateFoo(); // if this returns MyFoo,
foo.Write("1"); // it stills calls GeneratedFoo.Write
This is expceted since it is not a virtual method. But I'm wondering if there is a way (a hack maybe) to make it call the derived method.
Thanks,
Ian
Adam gave you an answer (correct one). Now it's time for hack you were asking for :)
class BaseFoo
{
public void Write() { Console.WriteLine("Hello simple world"); }
}
class DerFoo : BaseFoo
{
public void Write() { Console.WriteLine("Hello complicated world"); }
}
public static void Main()
{
BaseFoo bs = new DerFoo();
bs.Write();
bs.GetType().GetMethod("Write").Invoke(bs, null);
}
Prints out:
Hello simple world
Hello complicated world
Without being able to make the method virtual, no. A non-virtual method is statically linked at compile time and can't be changed.
Write an extension method that safecasts to your derived type, and calls the method against that reference instead.
public static class Extensions
{
public static void WriteFoo(this GeneratedFoo foo, string p)
{
MyFoo derived = foo as MyFoo;
if (derived != null)
{
derived.Write(p);
}
else
{
foo.Write(p);
}
}
}
then call it with
GeneratedFoo unknownFoo;
unknownFoo.WriteFoo("win");
NB: this is a dirty hack. A clearer solution would be to ask yourself why you need to use the new modifier in the first place. Overloading the meaning of Write(p) will make your code confusing for maintainers. You could just as easily declare it public void WriteToTarget() or something much more specific to avoid that confusion in the first place.
Using "new" on a method is not overriding, its hiding the original method. This is completely different to polymorphism and should be avoided, its only purpose is for covariance/contra-variance of methods that perform an identical function (eg, public Foo Clone(); and public new Bar Clone();). The other purpose is for legacy code when an identically named method is added to a base class that you have no control over and cannot at this time change your method's name.
Though the two methods share the same name they are completely separate methods, it occupies a different slot in the class's method table, where as overriding replaces the existing method in a class's method table.
My solution to this would be to use an interface such as IFoo, and either edit the generated class or use a proxy class that delegates all its method calls to an instance of GeneratedFoo to implement IFoo.
public DelegatingFoo : IFoo
{
private GeneratedFoo foo;
public DelegatingFoo(GeneratedFoo foo) { this.foo = foo; }
public void Write(string p) { foo.Write(p); }
}
If the generated class has no virtual method then it is not possible. If you could modify the tool to generate the Write method as virtual then in MyFoo use the keyword override instead of new to qualify the Write method.
A second option would be to write a script/macro to change the source code of GeneratedFoo after the tool has run to inject the string "virtual" before desired methods as part of your build process.
What about a custom FX cop rule added to your build system?
An approach that you could use would be to actually define a few new classes all derived from GeneratedFoo; eg:
public class MyFooBase : GeneratedFoo
{
public virtual void MyMethod() { ... }
}
public class MyFoo1 : MyFooBase { ... }
public class MyFoo2 : MyFooBase { ... }
This would allow you to essentially add virtual methods to your generated class.