Calling inheriting class methods via interface - c#

Given the scenario...
interface IBase{
void Process(int value);
}
abstract class Base : IBase
{
public virtual void Process(int value){ throw new NotImplementedException(); }
}
class Implemented: Base, IBase
{
public void Process(int value)
{
// .. some code here..
}
}
I'm trying to write a loop similar to the following.
foreach( Base b in CollectionOfImplemented )
{
b.Process( // something will go here // );
}
Trying this, it keeps calling Base.Process, instead of Implemented.Process; but the type in the collection is Implemented, not Base. Boxing it seems to work, but I was hoping to see if I could find a more intelligent approach to it, since the Collection will contain other types of objects that also inherit from Base.

You need to explicitly override Process in Implemented:
class Implemented: Base
{
public override void Process(int value)
{
// .. some code here..
}
}
Or you won't get virtual method dispatching.
Also, if your base method is always going to throw that NotImplementedException, it should be marked as abstract instead.

I think you need to specify "override" for Process in your Implemented class.

Related

How to enforce a derived type for a method that is implemented from abstract?

My abstract class has a method that is abstract like this:
public abstract void Run(BaseType baseType);
And now in my derived class which has to implement this function, i want it to only accept a specific derived type from BaseType
So it would have:
public override void Run(DerivedType derivedType){}
Is there any way to enforce this at all ?
Currently i have to do:
public override void Run(BaseType baseType) {
if(!(baseType is DerivedType)) {
// throw exception
}
}
It's not very strict with enforcing the type - i was wondering if there is a way to do so without the need to constantly add a type check ?
I've sometimes used this pattern:
public interface IHandler
{
void Run();
}
public abstract class BaseHandler<TObj> : IHandler
where TObj: BaseType
{
protected readonly TObj _obj {get;set;}
public BaseHandler(TObj obj)
{
this._obj = obj;
}
public abstract void Run();
}
public class DerivedHandler : BaseHandler<DerivedType>
{
public DerivedHandler(DerivedType obj) : base(obj)
{
}
public override void Run()
{
// do stuff with base._obj
}
}
public class HandlerService
{
public IHandler CreateHandler<TObj>(TObj obj)
{
// Depending on your DI container, you could resolve this automatically from the container
if (typeof(TObj) == typeof(DerivedType))
{
return new DerivedHandler(obj);
}
throw new NotImplementedException();
}
}
This allows you to define a specific "handler" for each derived type, and then access it through a common interface.
The idea is that you instantiate a specific handler for the object, and then methods like Run() operate on that object. You can then resolve a handler through the service.
I'll fill in some more info later when I have time.
You want the language to do something that it really shouldn't. You want a covariant argument, which violates the Liskov Substitution Principle: It makes the implementation of the abstract class not usable in every situation where the abstract base class is usable. This is the whole point of abstract base classes to begin with.
Although it could make sense to have a covariant return type (returning a more derived type then the abstract methods specifies) the language also prevents you to do that.

Overriding explicit interface implementations?

What is the proper way to override explicit implementations of an interface in a child class?
public interface ITest
{
string Speak();
}
public class ParentTest : ITest
{
string ITest.Speak()
{
return "Meow";
}
}
public class ChildTest : ParentTest
{
// causes compile time errors
override string ITest.Speak()
{
// Note: I'd also like to be able to call the base implementation
return "Mooo" + base.Speak();
}
}
The above is a best guess for the syntax, but obviously it's wrong. It causes the following compile time errors:
error CS0621:
`ChildTest.ITest.Speak()': virtual or abstract members cannot be
private
error CS0540:
ChildTest.ITest.Speak()': containing type does not implement
interfaceITest'
error CS0106:
The modifier `override' is not valid for this item
I can actually get this to work without using explicit interfaces so it's not actually blocking me but I would really like know, for my own curiosity, what is the correct syntax if wanted to do this with explicit interfaces?
An explicit interface implementation cannot be a virtual member. See section 13.4.1 of the C# language specification (it is outdated but this logic does not appear to have changed in C# 6.0). Specifically:
It is a compile-time error for an explicit interface member
implementation to include access modifiers, and it is a compile-time
error to include the modifiers abstract, virtual, override, or static.
This means, you will never be able to directly override this member.
What you can do as a workaround is to call another virtual method from your explicit implementation:
class Base : IBla
{
void IBla.DoSomething()
{
this.DoSomethingForIBla();
}
protected virtual void DoSomethingForIBla()
{
...
}
}
class Derived : Base
{
protected override void DoSomethingForIBla()
{
...
}
}
I also had a situation where I thought I wanted to override an explicit interface implementation and call the base class and found this question with its answers saying "can't be done".
The first thing to note is that in order to override the explicit interface implementation WITHOUT calling the base class is fairly simple. The derived class merely needs to implement the interface itself.
public class ChildTest : ParentTest, ITest
{
string ITest.Speak()
{
return "Mooo";
}
// Note: any other interface functions will call ParentTest's implementation
}
However, there is now no "legitimate" way to call ParentTest's implementation of ITest.Speak on an object of type ChildTest, as any attempt to use the interface will result in ChildTest's implementation being called instead.
Thus, it is only the call to the base implementation that causes complication. To satisfy my curiosity, I proved that it CAN be done, but really it shouldn't...
Leaving the base class unchanged, the following does in fact allow the base class to be called using reflection.
public class ChildTest : ParentTest, ITest
{
string ITest.Speak()
{
return "Mooo" + typeof(ParentTest).GetMethod("ITest.Speak", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(this, new object[0]) as string;
}
}
NB if the sample code is enclosed in a namespace, the fully qualified interface name is required. e.g. "MyNamespace.ITest.Speak"
If the function will be called repeatedly and/or for many objects, performance can be improved by caching the method info, and/or creating a delegate for the base call, e.g.:
public class ChildTest : ParentTest, ITest
{
static ChildTest()
{
baseSpeakMethodInfo = typeof(ParentTest).GetMethod("ITest.Speak", BindingFlags.Instance | BindingFlags.NonPublic);
}
static private MethodInfo baseSpeakMethodInfo;
public ChildTest()
{
baseSpeak = baseSpeakMethodInfo.CreateDelegate(typeof(Func<string>), this) as Func<string>;
}
private Func<string> baseSpeak;
string ITest.Speak()
{
return "Mooo" + baseSpeak();
}
}
The only advantage this has over other answers is that it works if you cannot modify the base class. Otherwise, it's a horrible solution, and a mechanism should be created in the base class (as in other answers) to provide the derived class with a legitimate way to call the base implementation.
You can use a protected virtual method, and keep the implementation non-public, so you still have explicit interface implementation which is just a wrapper around the implementation:
public class ParentTest : ITest
{
protected virtual string Speak_Impl()
{
return "Meow";
}
string ITest.Speak()
{
return Speak_Impl();
}
}
public class ChildTest : ParentTest
{
protected override string Speak_Impl()
{
return "Mooo";
}
}
You can't override explicit interface implementations. They cannot be virtual so there's no way to directly override them. You can, however, make them indirectly virtual by having it call a protected virtual member:
public interface ITest
{
string Speak();
}
public class ParentTest : ITest
{
string ITest.Speak()
{
return Speak();
}
protected virtual string Speak()
{
return "Meow";
}
}
public class ChildTest : ParentTest
{
protected override string Speak()
{
return "Mooo";
}
}
public virtual string Speak() in the parent and public override string Speak() in the child should work fine. You cannot use explicit interfaces for this use case. You can work around it by declaring a protected member and calling it in the explicit interface implementations if you need to use them.

Template method pattern - prevent direct method calls in derived classes

I'm not sure if I understand template method pattern correctly.
Here is my simplified base class implementation:
public abstract class AlgorithmBase
{
protected void AlgorithmMethod()
{
if(!OnSimulationStart())
{
OnSimulationEnd(false);
return;
}
if(!DoSomeStep())
{
OnSimulationEnd(false);
return;
}
OnSimulationEnd(true);
}
protected abstract bool OnSimulationStart();
protected abstract bool DoSomeStep();
protected abstract void OnSimulationEnd(bool result);
}
As far as I understand it, base class knows algorithm flow and manages it.
The problem is that in real project I have many abstract methods and it would be nice if I could somehow prevent direct calling them in derived classes. It is unreadable when more than one class manages algorithm flow.
A trick based on explicit implementation of an interface can be used to prevent accidental invokes of method required by the base algorith implementation. However, it's such a safety measure, which can be broken, but the chances are high that the developer would know what he would be doing.
An interface declaring methods required by AlgorithmMethod:
public interface IAlgorithmMethodImpl
{
bool OnSimulationStart();
bool DoSomeStep();
void OnSimulationEnd(bool result);
}
Base abstract class that uses this interface, passed into its constructor, to call required methods:
public abstract class AlgorithmBase
{
protected AlgorithmBase(IAlgorithmMethodImpl impl)
{
Impl = impl;
}
// can be a property reasonable cases; however, a field
// fits well into our scenario
private IAlgorithmMethodImpl Impl;
protected void AlgorithmMethod()
{
if(!Impl.OnSimulationStart())
{
Impl.OnSimulationEnd(false);
return;
}
if(!DoSomeStep())
{
Impl.OnSimulationEnd(false);
return;
}
Impl.OnSimulationEnd(true);
}
// no abstract method declarations here — they are provided by 'Impl'
}
Then the specific algorithm class that inherits from AlgorithmBase uses explicit interface implementation to encapsulate implementation of the necessary methods (like with abstract methods declared in the base) class while preventing them being invoked accidentally:
public class MySuperAlgorithm : AlgorithmBase, IAlgorithmMethodImpl
{
public MySuperAlgorithm()
// pass a reference to this instance as the class
// that implements the required methods
: base(this)
{
}
// explicit implementation of IAlgorithmMethodImpl
bool IAlgorithmMethodImpl.OnSimulationStart() { ... implementation ... }
bool IAlgorithmMethodImpl.DoSomeStep() { ... implementation ... }
void IAlgorithmMethodImpl.OnSimulationEnd(bool result) { ... implementation ... }
}
The advantage of this approch — besides preventing accidental invoking of implementation methods — is that you can choose whether encapsulate the implementation in the descendant, or to decompose it into a separate class.

virtual calls on overridden interface implementations

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.

Is it possible to override a non-virtual method?

Is there any way to override a non-virtual method? or something that gives similar results (other than creating a new method to call the desired method)?
I would like to override a method from Microsoft.Xna.Framework.Graphics.GraphicsDevice with unit testing in mind.
No, you cannot override a non-virtual method. The closest thing you can do is hide the method by creating a new method with the same name but this is not advisable as it breaks good design principles.
But even hiding a method won't give you execution time polymorphic dispatch of method calls like a true virtual method call would. Consider this example:
using System;
class Example
{
static void Main()
{
Foo f = new Foo();
f.M();
Foo b = new Bar();
b.M();
}
}
class Foo
{
public void M()
{
Console.WriteLine("Foo.M");
}
}
class Bar : Foo
{
public new void M()
{
Console.WriteLine("Bar.M");
}
}
In this example both calls to the M method print Foo.M. As you can see this approach does allow you to have a new implementation for a method as long as the reference to that object is of the correct derived type but hiding a base method does break polymorphism.
I would recommend that you do not hide base methods in this manner.
I tend to side with those who favor C#'s default behavior that methods are non-virtual by default (as opposed to Java). I would go even further and say that classes should also be sealed by default. Inheritance is hard to design for properly and the fact that there is a method that is not marked to be virtual indicates that the author of that method never intended for the method to be overridden.
Edit: "execution time polymorphic dispatch":
What I mean by this is the default behavior that happens at execution time when you call virtual methods. Let's say for example that in my previous code example, rather than defining a non-virtual method, I did in fact define a virtual method and a true overridden method as well.
If I were to call b.Foo in that case, the CLR would correctly determine the type of object that the b reference points to as Bar and would dispatch the call to M appropriately.
No you can't.
You can only override a virtual method - see the MSDN here:
In C#, derived classes can contain methods with the same name as base class methods.
The base class method must be defined virtual.
You can't override non-virtual method of any class in C# (without hacking CLR), but you can override any method of interface the class implements.
Consider we have non-sealed
class GraphicsDevice: IGraphicsDevice {
public void DoWork() {
Console.WriteLine("GraphicsDevice.DoWork()");
}
}
// with its interface
interface IGraphicsDevice {
void DoWork();
}
// You can't just override DoWork in a child class,
// but if you replace usage of GraphicsDevice to IGraphicsDevice,
// then you can override this method (and, actually, the whole interface).
class MyDevice: GraphicsDevice, IGraphicsDevice {
public new void DoWork() {
Console.WriteLine("MyDevice.DoWork()");
base.DoWork();
}
}
And here's demo
class Program {
static void Main(string[] args) {
IGraphicsDevice real = new GraphicsDevice();
var myObj = new MyDevice();
// demo that interface override works
GraphicsDevice myCastedToBase = myObj;
IGraphicsDevice my = myCastedToBase;
// obvious
Console.WriteLine("Using real GraphicsDevice:");
real.DoWork();
// override
Console.WriteLine("Using overriden GraphicsDevice:");
my.DoWork();
}
}
If the base class isn't sealed then you can inherit from it and write a new method that hides the base one (use the "new" keyword in the method declaration). Otherwise no, you cannot override it because it was never the original authors intent for it to be overridden, hence why it isn't virtual.
I think you're getting overloading and overriding confused, overloading means you have two or more methods with the same name but different sets of parameters while overriding means you have a different implementation for a method in a derived class (thereby replacing or modifying the behaviour in it's base class).
If a method is virtual, you can override it using the override keyword in the derrived class. However, non-virtual methods can only hide the base implementation by using the new keyword in place of the override keyword. The non-virtual route is useless if the caller accesses the method via a variable typed as the base type as the compiler would use a static dispatch to the base method (meaning the code in your derrived class would never be called).
There is never anything preventing you from adding an overload to an existing class, but only code that knows about your class would be able to access it.
The answer to this question is not entirely No. It depends on how you structure your inheritance and access the instances of your classes. If your design meets the following, you would be able to override non-virtual method from base class with the new modifier:
The method is declared in an interface that your classes inherit from
You are accessing the class instances using the interface
Take example of the following:
interface ITest { void Test(); }
class A : ITest { public void Test(){Console.WriteLine("A");} }
class B : A { public new void Test(){Console.WriteLine("B");} }
ITest x = new B();
x.Test(); // output "A"
calling x.Test() will output "A" to the console. However if you re-declare the interface in the definition of class B, x.Test() will output B instead.
interface ITest { void Test(); }
class A : ITest { public void Test(){Console.WriteLine("A");} }
class B : A, ITest { public new void Test(){Console.WriteLine("B");} }
ITest x = new B();
x.Test(); // output "B"
In the case you are inheriting from a non-derived class, you could simply create an abstract super class and inherit from it downstream instead.
Is there any way to override a non-virtual method? or something that gives similar results (other than creating a new method to call the desired method)?
You cannot override a non-virtual method. However you can use the new modifier keyword to get similar results:
class Class0
{
public int Test()
{
return 0;
}
}
class Class1 : Class0
{
public new int Test()
{
return 1;
}
}
. . .
// result of 1
Console.WriteLine(new Class1().Test());
You will also want to make sure that the access modifier is also the same, otherwise you will not get inheritance down the line. If another class inherits from Class1 the new keyword in Class1 will not affect objects inheriting from it, unless the access modifier is the same.
If the access modifier is not the same:
class Class0
{
protected int Test()
{
return 0;
}
}
class Class1 : Class0
{
// different access modifier
new int Test()
{
return 1;
}
}
class Class2 : Class1
{
public int Result()
{
return Test();
}
}
. . .
// result of 0
Console.WriteLine(new Class2().Result());
...versus if the access modifier is the same:
class Class0
{
protected int Test()
{
return 0;
}
}
class Class1 : Class0
{
// same access modifier
protected new int Test()
{
return 1;
}
}
class Class2 : Class1
{
public int Result()
{
return Test();
}
}
. . .
// result of 1
Console.WriteLine(new Class2().Result());
As pointed out in a previous answer, this is not a good design principle.
There is a way of achieving this using abstract class and abstract method.
Consider
Class Base
{
void MethodToBeTested()
{
...
}
void Method1()
{
}
void Method2()
{
}
...
}
Now, if you wish to have different versions of method MethodToBeTested(), then
change Class Base to an abstract class and method MethodToBeTested() as an abstract method
abstract Class Base
{
abstract void MethodToBeTested();
void Method1()
{
}
void Method2()
{
}
...
}
With abstract void MethodToBeTested() comes an issue; the implementation is gone.
Hence create a class DefaultBaseImplementation : Base to have the default implementation.
And create another class UnitTestImplementation : Base to have unit test implementation.
With these 2 new classes, the base class functionality can be overridden.
Class DefaultBaseImplementation : Base
{
override void MethodToBeTested()
{
//Base (default) implementation goes here
}
}
Class UnitTestImplementation : Base
{
override void MethodToBeTested()
{
//Unit test implementation goes here
}
}
Now you have 2 classes implementing (overriding) MethodToBeTested().
You can instantiate the (derived) class as required (i.e. either with base implementation or with unit test implementation).

Categories