Given an interface IFoo
interface IFoo {
void Do();
void Stuff();
}
Let assume there are (legacy) classes Foo1, Foo2, Foo3 all implementing IFoo.
Stuff can be done by using some methods of IFoo, or in case of the newer classes, by just using DoStuff(). Actually, one might look at it as if DoStuff() was "forgotten" on IFoo.
There are also newer Classes FooX (FooY, ...) implementing IFoo2, in additional those has a method DoStuff();
interface IFoo2 : IFoo {
void DoStuff();
}
I need to accept IFoo objects, and be able to "Do Stuff" on it.
//Let us assume foos = new IFoo[] {new Foo1(), new Foo2(), new Foo3(), new FooX()};
void MyMethod(IFoo[] foos){
foreach(foo in foos){
//DoStuff is not defined in IFoo
foo.DoStuff();
}
}
So, I thought to just define an extension method DoStuff() on IFoo for the legacy classes
public static DoStuff(this IFoo self){
self.Do();
self.Stuff();
}
Unfortunately, this extension method is always called, even for FooX.
I Could do something like
public static DoSomeStuff(this IFoo self){
if(self is IFoo2) {
(self as IFoo2).DoStuff()
} else {
self.Do();
self.Stuff();
}
}
void MyMethod(IFoo[] foos){
foreach(foo in foos){
foo.DoSomeStuff();
}
}
However, the method MyMethod reside in a legacy project, currently not yet aware of IFoo2. Is it possible to find a solution without using IFoo2?
You shouldn't extend IFoo interface, like that. It's break Interface Segregation principle.
If these object represents exactly the same entity in your code you shouldn't use different interfaces for them.
You might create extension method if you want extend functionality of classes which implements interface IFoo, but don't create second interface which represents the same contract. However if you want to change IFoo contract - refactor legacy objects (add missing implementation).
As long as your variable has the type IFoo, the extension method DoStuff will be called. The usual way of solving this is exactly what you propose in your last paragraph, or ensuring that you use IFoo2 instead of IFoo in places where you want the newer interface method to be called.
You can create an abstract subclass that implements the methods Do and Stuff for the classes that at the current time don't implement it.
public abstract class abstractFoo : IFoo
{
public virtual void Do() {}
public virtual void Stuff(){}
}
If you can then inherit from this abstract class
public class Foo: IFoo
{
// interface implementation required
}
becomes:
public class Foo: abstractFoo
{
// interface implementation NOT required
}
IMHO FooX shouldn't be implementing IFoo to begin with and some reconsideration should be made of your current arquitecture.
That said, and not knowing exactly what limitations you are fighting against, could you send the IFooXs through a wrapper? Something like the following:
public class FooXWrapper<T>: IFoo where T: FooX
{
readonly T foo;
bool doCalled;
public FooWrapper(T foo)
{
this.foo = foo;
}
public void Do()
{
doCalled = true;
}
public void Stuff()
{
if (!doCalled)
throw new InvalidOperationException("Must call Do");
foo.DoStuff();
}
}
Its an ugly hack, but given the circumstances...
Related
Please consider the following program:
using System;
public interface IFoo
{
void DoFoo();
}
public class Bar: IFoo
{
public void DoFoo() => Console.WriteLine("BAR!");
}
public class Baz: Bar, IFoo
{
void IFoo.DoFoo() => Console.WriteLine("baz!");
}
class Program
{
static void Main()
{
Baz baz = new Baz();
baz.DoFoo();
IFoo foo = baz;
foo.DoFoo();
Bar bar = baz;
bar.DoFoo();
IFoo foobar = bar;
foobar.DoFoo();
}
}
It gives the following output which I personally with my C++ background consider highly unexpected:
BAR!
baz!
BAR!
baz!
Having , IFoo in the declaration of Baz seems to be substantial, because otherwise void IFoo.DoFoo() doesn't compile.
Can someone please explain what is going on here (especially the last line)? And what should be done to prevent such behavior in real life? Should one avoid implementing from the same interface at all or there are some other rules to avoid problems?
UPD:
Looks like the principal problem here is not with "multiple inheritance" (which is not real multiple inheritance actually), but with the way interface methods can be implemented in C#. Namely, one can have two different implementations of the same method in the same class, one of which is explicit, another is implicit. E.g. this program:
using System;
public interface IFoo
{
void DoFoo();
}
public class Bar: IFoo
{
void IFoo.DoFoo() => Console.WriteLine("Foo!");
public void DoFoo() => Console.WriteLine("BAR!");
}
class Program
{
static void Main()
{
Bar baz = new Bar();
baz.DoFoo();
IFoo foo = baz;
foo.DoFoo();
}
}
prints
BAR!
Foo!
The trick with "multiple inheritance" just allows to introduce the explicit implementation from a derived class.
From my point of view this feature of C# is potentially dangerous, because if one implements a method of an interface, one usually expects the same method will be called no matter if it is invoked from the interface or from the class. And this is really the case if one implements everything only explicitly or only implicitly. But if both ways are used, this assumption is broken. So the moral seems to be:
Don't mix implicit and explicit implementation of the same method if you don't have in mind to employ this strange effect for some purpose.
Use explicit implementation in derived classes with caution.
This is a difference in the explicit implementation (void IFoo.DoFoo()) vs the implicit implementation (public void DoFoo()). The compiler will use the explicit implementation first. If you provide both an explicit and implicit implementation then the difference becomes clear:
https://dotnetfiddle.net/7l9gIs
using System;
public interface IFoo
{
void DoFoo();
}
public class Bar: IFoo
{
public void DoFoo(){ Console.WriteLine("BAR!"); }
}
public class Baz: Bar, IFoo
{
void IFoo.DoFoo(){ Console.WriteLine("baz explicit!"); }
public new void DoFoo(){ Console.WriteLine("baz implicit!"); }
}
public class Program
{
public static void Main()
{
Baz baz = new Baz();
baz.DoFoo();
IFoo foo = baz;
foo.DoFoo();
Bar bar = baz;
bar.DoFoo();
IFoo foobar = bar;
foobar.DoFoo();
}
}
Output
baz implicit!
baz explicit!
BAR!
baz explicit!
Implicit implementations tend to be more common and more convenient for usage. They are less verbose and any usage of the concrete type will have the implementations of the members exposed. Implicit implementations don't include the name of the interface being implemented before the member name, so the compiler infers this. The members will be exposed as public and will be accessible when the object is cast as the concrete type.
Visit this link for more details https://www.pluralsight.com/guides/distinguish-explicit-and-implicit-interface-implementation-csharp
The confusion is starting when you implement Baz from IFoo. Because Bar is already implements IFoo and Baz is the subclass of Bar. So, you dont need to do that.
In object oriented programming its not a best practice, in fact it is worst practice.
If you want to override DoFoo method, use the following code
public interface IFoo
{
void DoFoo();
}
public class Bar : IFoo
{
public virtual void DoFoo()
{
// do something
}
}
public class Baz : Bar
{
public override void DoFoo()
{
// override what you did in Bar class
}
}
In your code, when you try to baz.DoFoo, in fact you are calling bar.DoFoo.Because you didnt override it. Its the problem.
In the following sample class "SomeClass" does not implement "ISomeInterface". Why can't I implement this by passing a more derived interface which does implement the base requirement. Whatever instance would be passed it would still implement the base, am I missing something?
namespace Test
{
public interface IBaseInterface
{
void DoBaseStuff();
}
public interface IChildInterface : IBaseInterface
{
void DoChildStuff();
}
public interface ISomeInterface
{
void DoSomething(IBaseInterface baseInterface);
}
public class SomeClass : ISomeInterface
{
public void DoSomething(IChildInterface baseInterface)
{
}
}
}
This restriction exists because the ISomeInterface expects that any IBaseInterface will satisfy the contract. That is, if you have the following:
public interface IBase {}
public interface IChildA : IBase {}
public interface IChildB : IBase {}
And an interface that expects IBase:
public interface IFoo { void Bar(IBase val); }
Then restricting this in a derived class as you would like:
public class Foo : IFoo { public void Bar(IChildA val) {} }
Would create the following problem:
IChildB something = new ChildB();
IFoo something = new Foo();
something.Bar(something); // This is an invalid call
As such, you're not implementing the contract you said you would.
In this situation, you have two simple options:
Adjust IFoo to be generic, and accept a T that is a derivation of IBase:
public interface IFoo<T> where T : IBase { void Bar(T val); }
public class Foo : IFoo<IChildA> { public void Bar(IChildA val) {} }
Of course, this means that Foo can no longer accept any IBase (including IChildB).
Adjust Foo to implement IFoo, with an additional utility method for void Bar(IChildA val):
public class Foo : IFoo
{
public void Bar(IBase val) {}
public void Bar(IChildA val) {}
}
This has an interesting side-effect: whenever you call ((IFoo)foo).Bar it will expect IBase, and when you call foo.Bar it will expect IChildA or IBase. This means it satisfies the contract, while also having your derived-interface-specific method. If you want to "hide" the Bar(IBase) method more, you could implement IFoo explicitly:
void IFoo.Bar(IBase val) { }
This creates even more inconsistent behavior in your code, as now ((IFoo)foo).Bar is completely different from foo.Bar, but I leave the decision up to you.
This means, with the second version in this section, that foo.Bar(new ChildB()); is now invalid, as IChildB is not an IChildA.
Why can't I implement this by passing a more derived interface which does implement the base requirement. Whatever instance would be passed it would still implement the base, am I missing something?
This is not allowed because of the reasoning I mentioned above, IFoo.Bar expects any IBase, whereas you want to further constrain the type to IChildA, which is not a super-interface of IBase, and even if it were it would not be allowed because it violates the interface implementation, though you could more easily define a second method at that point that does what you want.
Keep in mind that when you implement an interface, you subscribe to a contract, and C# will not let you violate that contract.
This violates the Liskov substitution principle.
ISomeInterface guarantees that the method can be called with any IBaseInterface instance. Your implementation cannot limit that to only accept IChildInterface interfaces.
From MSDN:
When a class or struct implements an interface, the class or struct must provide an implementation for all of the members that the interface defines
This method in the derived
void DoSomething(IChildInterface baseInterface)
Does not have the same signature as the one in the interface:
void DoSomething(IBaseInterface baseInterface)
IChildInterface and IBaseInterface are not the same types. Therefore your derived class does not implement all methods of the interface and you get the compilation error.
For a possible the logic behind having this as a restriction instead of the compiler understanding the inheritance see Liskov's substitution principle as in SLakes answer
You should change some interface to use some type which implements IBaseInterface,
then change the method signatures to use whichever child your SomeClass wants.
public interface ISomeInterface<TSomeChild> where TSomeChild : IBaseInterface
{
void DoSomething(TSomeChild baseInterface);
}
public class SomeClass : ISomeInterface<IChildInterface>
{
public void DoSomething(IChildInterface baseInterface)
{
}
}
If you could do that, then you could do this:
IAnimal cat = new Cat();
IAnimalTrainer dogTrainer = new DogTrainer();
dogTrainer.Train(cat);
An IAnimalTrainer can train any IAnimal. But a DogTrainer can only train Dogs. Thus it's illegal for DogTrainer to implement the IAnimalTrainer interface.
In an Abstract class there are two abstract methods Method1() and Method2(),
but I like to inherit only one Method1() in derived Class, how to handle the situation?
public abstract class BaseClass
{
public abstract void Method1();
public abstract void Method2();
}
Really you can't... If you have to (and I would really question the reasons) some options are:
If you do not have any control over the abstract classes involved, and must use this specific abstract class, then, only way is to make the implementation in derived class throw a NotImplementedException.
public MyDerivedClass: BaseClass
{
public override void Method1()
{
// implementation of Method1
}
public override void Method2()
{ throw new NotImplementedException(); }
}
... or create another abstract base class called, say OnlyDOMethod1
public abstract class OnlyDoMethod1
{ public abstract void Method1(); }
then, modify Baseclass so it inherits from OnlyDoMethod1
public abstract class BaseClass: OnlyDoMethod1
{ public abstract void Method2(); }
and use OnlyDoMethod1 anywhere you only want Method1
public MyDerivedClass: OnlyDoMethod1
{
public override void Method1()
{
// implementation of Method1
}
}
It sounds like what you're looking for is interfaces. Something like this:
public interface ICanDoMethod1
{
void Method1();
}
public interface ICanDoMethod2
{
void Method2();
}
Then in your classes you can selectively implement them:
public class JustMethod1 : ICanDoMethod1
{
// implement Method1 here
}
public class Both : ICanDoMethod1, ICanDoMethod2
{
// implement both here
}
// etc.
Essentially, any given class either can or can not be polymorphically interpreted as any given type. If you want to be only part of a type, then what you really have is two types. C# is single-inheritance, so to implement multiple types you would use interfaces.
Conversely, you could also chain your inheritance. Something like this:
public abstract class Base1
{
public abstract void Method1();
}
public abstract class BaseBoth : Base1
{
public abstract void Method2();
}
public class JustOne : Base1
{
// only implement Method1 here
}
public class Both : BaseBoth
{
// implement both here
}
That'll work if the options stack, that is if you don't want to be able to pick and choose and either want "1" or "1 and 2" (but not just "2").
As a last resort, you can "selectively implement" methods by explicitly not implementing the others. It would looks something like:
public class JustOne : BaseClass
{
public override void Method1()
{
// implement
}
public override void Method2()
{
throw new NotImplementedException();
}
}
But this would be something of an anti-pattern, where your objects would advertise functionality that they intentionally do not support. This would mean that the type BaseClass should be considered very unstable/unreliable, because there's no way for anything consuming that type to know how it should actually behave.
Ultimately, it sounds like you've painted yourself into a corner with your types and you need to back up a little and re-think them. Liskov Substitution shouldn't be taken so lightly.
This is basic example of violation of one of SOLID principles Interface segregation principle
A client should never be forced to implement an interface that it
doesn’t use or clients shouldn’t be forced to depend on methods they
do not use
If you have abstraction where you need only some of method you need to split them in separated abstractions.
.NET do not support multi-inheritance from classes, nut have nice workaround for this problem -> interfaces.
If you care about your code, then you have only one option - split abstract class into two separated classes which have only one method.
If you work only with abstraction then interfaces is better approach, because you can implement multiply interfaces in one class.
public interface IMethodOne
{
void Method1();
}
public interface IMethodTwo
{
void Method2();
}
Then you can implement that both interfaces in the class which needs both methods. And use only one interface in the class with one method needs.
public abstract class BaseClass : IMethodOne, IMethodTwo
{
public abstract void Method1();
public abstract void Method2();
}
And class with one method
public abstract class BaseClassOneMethod : IMethodOne
{
public abstract void Method1();
}
I would like this program to compile, and then print the output below:
public interface IFoo
{
void Bar();
}
public class FooBase : IFoo
{
void IFoo.Bar()
{
Console.WriteLine("Hello from base class.");
}
}
public class Foo : FooBase, IFoo
{
void IFoo.Bar()
{
(base as IFoo).Bar(); // doesn't compile
Console.WriteLine("Foo added some behavior!");
}
}
public static class Program
{
public static void Main(string[] args)
{
var foo = new Foo() as IFoo;
foo.Bar();
}
}
Desired output:
Hello from base class.
Foo added some behavior!
Obviously, the code above doesn't compile, because it's an invalid way to use the base keyword. Is there a way to accomplish this, without changing the implementation in the base class to a non-explicit one?
You can simply have the explicit interface implementation in the base class call a protected method in the class for its implementation. This allows other derived classes to still call that protected method while still explicitly implementing the interface (and also not publicly exposing the interface's method through the type itself, which presumably is the actual goal).
Is it possible to have an interface with two methods, suppose Add() and Subtract(), and implement the Add() method in class A and the Subtract() method in class B?
You cannot do that. If you are implementing an interface in a class, you have to provide implementation for all the methods in the interface. WCF contracts and services are no exception.
You can do it with inheritance:
public interface IFooBar
{
void Foo();
void Bar();
}
public class Fooer
{
public void Foo()
{
}
}
public class FooBar : Fooer, IFooBar
{
public void Bar()
{
}
}
You can apply the IFooBar interface to the FooBar class, because it implements the Foo() interface method through inheriting the Fooer class.
But in general you don't want to.