I defined a generic method Use<T>
in an interface IInterface
. I tried to make an implementation of that interface where the concrete implementation of the Use<T>
method depends on the actual type T
, and I want to always call the most specialized method. But it does not work:
interface IInterface { void Use<T>(T other) where T : IInterface; }
interface IChildInterface : IInterface { }
class ImplementsIInterface : IInterface
{
public void Use<T>(T other) where T : IInterface
{
Debug.WriteLine("ImplementsInterface.Use(IInterface)");
}
}
class ImplementsChildInterface : IChildInterface
{
public void Use<T>(IChildInterface other) where T : IInterface
{ // idea: if other is IChildInterface, use this method
Debug.WriteLine("ImplementsChildInterface.Use(IChildInterface)");
}
public void Use<T>(T other) where T : IInterface
{ // idea: if above method is not applicable, use this method
Debug.WriteLine("ImplementsChildInterface.Use(IInterface)");
}
}
Here is my main method:
public static void Main()
{
IChildInterface childinterf = new ImplementsChildInterface();
childinterf.Use(new ImplementsChildInterface()); // outputs "ImplementsChildInterface.Use(IInterface)"
// but should output "ImplementsChildInterface.Use(IChildInterface)"
childinterf.Use(new ImplementsIInterface()); // outputs "ImplementsChildInterface.Use(IInterface)"
}
The method that takes an IChildInterface
argument is never called, although it should.
Is there a way to make this work? Or is my approach fundamentally wrong?
Note that it is a necessity that IInterface
only has one method definition. I might enlarge the interface hierarchy at any time (and thus increase the number of implementations I could provide in an implementing class), but this should not lead to needing to add more method definitions in IInterface
. Otherwise, the whole point of using interfaces (i.e. to be flexible) would be missed.
The answers I got so far all involve the need to cast. This is also something I don't want to do, since it makes the whole setup useless. Let me explain the broader picture of what I try to achieve:
Let's imagine we created some instance of an IInterface
(like so: IInterface foo = new ImplementsChildInterface();
). It will behave in a certain way, but it will always behave in the same way - no matter if we see it as an IInterface
, an IChildInterface
or an ImplementsChildInterface
. Because, if we call some method on it, the compiler (or runtime? i don't know) will check what type it REALLY is and run the method defined in that type.
Now imagine we have two instances i1
and i2
of IInterface
. They again are, under the hood, concrete implementations of IInterface
, so they have a concrete behaviour, no matter through which glasses we seem them.
So when I run i1.Use(i2)
, the compiler (or runtime?) should be able to find out what i1
and i2
REALLY are, and run the corresponding method. Like so:
- Which type does
i1
have?ImplementsChildInterface
, ok, then I'll look at the methods there. - Which type does
i2
have?ImplementsIInterface
, ok, then let's see if there exists a methodUse(ImplementsIInterface ...)
. There is none, but maybe there is a fallback?ImplementsIInterface
is aIInterface
, so let's see if there exists a methodUse(IInterface ...)
. Yes, it exists, so let's call it!
Neither
IInterface
norIChildInterface
have a memberUse<T>(IChildInterface other)
defined, but onlyUse<T>(T other)
.Your class
ImplementsChildInterface
on the other side has a methodUse<T>(IChildInterface other)
. As you declaringchildInterf
as a reference of typeIChildInterface
you can´t access that member, but unly those defined in the interface. So you should cast to the actual class in order to access the method accepting an instance ofIChildInterface
. But even then the generic implementation is used. So you should also cast your parameter toIchildInterface
:Furthermore as you don´t use the generic type-parameter within your more specialized method, you can also omit it:
Alternativly you may also add a method into your
IChildInterface
:Now you can use
which will print the desired output.