generic methods: how to force using the most specialized method available - c#

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 method Use(ImplementsIInterface ...). There is none, but maybe there is a fallback? ImplementsIInterface is a IInterface, so let's see if there exists a method Use(IInterface ...). Yes, it exists, so let's call it!

Neither IInterface nor IChildInterface have a member Use<T>(IChildInterface other) defined, but only Use<T>(T other).
Your class ImplementsChildInterface on the other side has a method Use<T>(IChildInterface other). As you declaring childInterf as a reference of type IChildInterface 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 of IChildInterface. But even then the generic implementation is used. So you should also cast your parameter to IchildInterface:
ImplementsChildInterfacechildinterf = new ImplementsChildInterface();
childinterf.Use(((IChildInterface)new ImplementsChildInterface());
childinterf.Use(new ImplementsIInterface());
Furthermore as you don´t use the generic type-parameter within your more specialized method, you can also omit it:
class ImplementsChildInterface : IChildInterface
{
public void Use(IChildInterface other)
{ // 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)");
}
}
Alternativly you may also add a method into your IChildInterface:
void Use<T>(IChildInterface other) where T : IChildInterface;
Now you can use
IChildInterface childinterf = new ImplementsChildInterface();
childinterf.Use<IChildInterface>(new ImplementsChildInterface()); // outputs "ImplementsChildInterface.Use(IInterface)"
which will print the desired output.

Related

Why calling method on interface uses base implementation instead of override?

I have a problem with my code.
I would expect that since I'm constructing the Implementation object; every time I call Method() I'd use actual Implementation.Method() and not it's abstract's Base.Method(). It does not seem reasonable that I have to downcast to actual implementer or specify interface explicitly (So interfaces are not transitive in C#? I will call the "first proper instance of interface implementer" and not my class?)
I have a structure similar to this (simplified for clarity):
https://dotnetfiddle.net/oYVlQO
using System;
public interface IBase
{
string Method();
}
public abstract class Base : IBase
{
public string Method() { return "Sample"; }
}
public class Implementation : Base // if I add ", IBase" to this it works as expected, but why?
{
new public string Method() { return "Overriden"; }
}
public class Program
{
// and it's used like so...
public static void Main()
{
IBase b = new Implementation();
//Implementation b = new Implementation(); // It works as expected, always using Implementation.Method();
Console.WriteLine(b.Method()); // Produces "Sample", so Base.Method(). Why not implementation?
Console.WriteLine(((Implementation) b).Method()); // Produces "Overriden", so Implementation.Method(); Since when I have to downcast to use overriden method!?
}
}
}
I'm really scratching my head over this; Especially that the same code in Java works "as I would expect" https://repl.it/repls/VitalSpiritedWebpage
I've tried to find it in the c# specs to no avail, maybe I do not have the proper keywords...
In cause of the question, which is:
Why is it that way?
My answer:
Because you don’t override the method but hide it.
The interface is implemented by the baseclass, so the Method is called on the base-class.
To answer the question, which isn’t asked:
How would it work?
Answer:
using System;
public interface IBase
{
string Method();
}
public abstract class Base : IBase
{
public virtual string Method() { return "Sample"; }
}
public class Implementation : Base
{
public override string Method() { return "Overriden"; }
}
You may want to take a look at the part of the C# spec that deals with interface re-implementation.
When you access a member through the interface, it begins its lookup at the most derived type that explicitly implements that interface. In your example, the most derived type is Base and so it calls the method that's present there.
When you added IBase to the list of interfaces explicitly implemented by Implementation it worked, because that's the new starting point for lookup and it finds your new method.
You can either solve your problem by making the base member virtual and then overriding it in derived classes, or you can re-implement the interface by including that in the list for your Implementation class.
So the problem in my sample code is two-fold.
I assumed that in C# methods are "virtual" by default (as is in Java). Since I'm usually coding in Java, I've made an incorrect assumption.
See Is it possible to override a non-virtual method?
If I'd use virtual, I could override the method and achieve exactly the output I expected, as described in doc:
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/virtual namely "When a virtual method is invoked, the run-time type of the object is checked for an overriding member. The overriding member in the most derived class is called, which might be the original member, if no derived class has overridden the member."
My code, hovewer, is using method hiding, so unless I inform the compiler about my intention of using my implementation, it'll default to non-hidden method (as resolved by abstract class being the actual, original implementer)

Generic type constraint for significant classes

Is it possible to define generic constraint for multiple classes that doesn't share a base class/interface?
For ex.
class A
{
}
class B
{
}
class C
{
void Test<T>(T someObj)
{
...
}
}
I want to pass either class A or B to Test method, nothing else.
I know that I can put a where statement with the base class/interface of A or B but I can't specify base interface/class for the related classes in my situation.
No, and it doesn't make sense to do so. It isn't a generic any more. If class A and B share properties, methods, etc, they should share the same interface or base class. If not, they are not 'the same' and can't be treated as such.
Guess what would happen if you changed the method signature in one of the two classes. Suddenly that method isn't 'shared' any more. The compiler doesn't try to determine what methods and properties can be considered shared, instead it doesn't support the feature you request.
An option would be to use two methods (one overload of every type) which introduces repeating code, which is bad of course. It would be better to use an interface, or if it is really out of you hands dynamic, although I try to minimize the use of it.
No this is not possible in compile time.
If it would be, how would you use the generic parameter type T? Would it behave like A or like B?
Consider the following:
class A
{
public void MethodInA();
}
class B
{
public void MethodInB();
}
class C
{
// pseudocode here!
void Test<T>(T someObj) where T : A or B
{
// how it would behave if T is B?
someObj.MethodInA();
// how it would behave if T is A?
someObj.MethodInB();
}
}
Instead extract some base class or interface, that will be common for both A and B classes and use it in your generic method constraint.
If there's nothing shared, then:
void Test(A obj) {}
void Test(B obj) {}
is the only real way to do it. You could make the generic method private, and the overloads public, and just call the private method from the overloads, as in:
private void TestImplementation<T>(T object) { ... }
public void Test(A obj) { this.TestImplementation(obj); }
public void Test(B obj) { this.TestImplementation(obj); }

Two-step method resolution with inheritance and generic constraints

I've encountered something quite surprising when using generic constraints with inheritance. I have an overloaded methods Foo that differ with parameter - either base or derived class instance. In both cases it's generally just passing the instance to the second pair of overloaded methods - Bar.
When I call Foo with base class instance, Bar overload for the base class is called. When I call Foo with derived class instance, Bar overload for the derived class is called. This is clear and expected.
But when I tried to merge Foo methods into single one GenericFoo that use generics and constraints, methods are resolved differently - T is resolved correctly, but only base-class overload of Bar is called.
public class Animal { }
public class Cat : Animal { }
public class AnimalProcessor
{
public static void Foo(Animal obj)
{
Console.WriteLine("Foo(Animal)");
Bar(obj);
}
public static void Foo(Cat obj)
{
Console.WriteLine("Foo(Cat)");
Bar(obj);
}
// new generic method to replace the two above
public static void GenericFoo<T>(T obj)
where T : Animal
{
Console.WriteLine("Foo(generic)");
Bar(obj);
}
public static void Bar(Animal obj)
{
Console.WriteLine("Bar(Animal)");
}
public static void Bar(Cat obj)
{
Console.WriteLine("Bar(Cat)");
}
}
Testing code - two first cases for non-generic old methods, two last for new generic method.
Console.WriteLine("Animal()");
AnimalProcessor.Foo(new Animal());
Console.WriteLine();
Console.WriteLine("Cat()");
AnimalProcessor.Foo(new Cat());
Console.WriteLine();
Console.WriteLine("Animal()");
AnimalProcessor.GenericFoo(new Animal());
Console.WriteLine();
Console.WriteLine("Cat()");
AnimalProcessor.GenericFoo(new Cat());
Console.ReadLine();
And the result - note the difference in type resolved in Bar:
Animal()
Foo(Animal)
Bar(Animal)
Cat()
Foo(Cat)
Bar(Cat)
Animal()
Foo(generic)
Bar(Animal)
Cat()
Foo(generic)
Bar(Animal)
It looks like the compiler binds all calls from GenericFoo to the least specific overload, even if all more specific-typed calls are known at compile time. Why is that, what is the reason for such behaviour? Which part of specs defines this?
Per OP's request, comment re-posted as answer:
Generics are not templates. Generic methods are compiled once and their behavior is for the 'most generic' case (in this case, Animal.) This is different from C++ style templating, where the template is compiled separately for each specialization by type.
The generic C# method is compiled into a generic IL method. And in IL, you have to explicitly specify which overload you are calling. So there is no simple way how the compiler could have done this. (There is complicated way: run a mini-compiler that chooses the overload at this point dynamically, which is what dynamic does.)
If you want this behavior, one option would be to make Bar() a virtual method on Animal. Another option would be using dynamic.

C# generic factory method

Perhaps this is a simple newbie C# question, but so be it---it will be a fresh break from my other questions, which are so difficult that no one knows the answer to them. :)
Let's say I have a generic type in C#:
Thing<T>
And let's say I want to make a thing using a static factory method. In Java, this is no problem:
public static <T> Thing<T> createThing()
{
return flag ? new Thing<Integer>(5) : new Thing<String>("hello");
}
How do I do this in C#? Thanks.
If you want to return an instance of a templated class using one of many different template arguments, one way to do it is with an abstract base (or an interface):
abstract class UntypedThing { }
class Thing<T> : UntypedThing
{
public Thing(T t) { }
}
class Foo
{
public static UntypedThing createThing(bool flag)
{
if (flag)
return new Thing<int>(5);
else return new Thing<String>("hello");
}
}
The UntypedThing class would contain as much code as possible that does not rely on the template type. The Thing class would ideally only contain code that relies on the template type. The factory class Foo always returns the former.
You can in theory use reflection to build up the correct generic type, but it will be pretty useless to you as at some point you will need to upcast it to a less specific type.
public class ThingFactory {
public object Create(bool flag) {
Type outputType = null;
if(flag) {
outputType = typeof(string);
} else {
outputType = typeof(int);
}
return Activator.CreateInstance(typeof(Thing<>).MakeGenericType(outputType));
}
}
As you can see, the value of doing this is about zero as you will need to cast the return type to the type you want, meaning that the logic to determine it needs to live outside the Create method.
I would use Reinderien's method and have a non-generic base. This is the most sane and idiomatic approach.
Oh, the trouble I get myself in when I simply try to do something simple.
It turns out that C# 4 allows this sort of covariance---sort of. First, I have to make Thing an interface and specify the "out" generic parameter:
public interface Thing<out T> {...}
But if I do certain things, C# won't let me use covariance. For example, if I try to return T from the interface:
public interface Thing<out T>
{
public T GetT();
Even if I manage to get covariance with Thing, what do I do with it?
Thing<object> thing=createThing();
The compiler tells me that the type cannot be inferred from usage.
Let's say I say screw the whole T thing and make the factory method return Thing of type object:
public static Thing<object> createThing() {...}
Fine, but now where do I put it?
IList<Thing<object>> list=new List<Thing<object>>();
Thing<object> thing=createThing();
list.Add(thing);
Yes, I have to say that this is a list of Thing with T of type Object, because C# has no wildcard type.
If this were Java, I'd simply say:
public class Thing<T> {...}
public static <T> Thing<T> createThing() {...}
List<?> things=new ArrayList<Thing<?>>();
Thing<?> thing=createThing();
things.add(thing);
If I wanted extra safety by saying that T had to be of a special type, I'd say:
public static <T extends MyBaseType> Thing<T> createThing() {...}
List<? extends MyBaseType> things=new ArrayList<Thing<? extends MyBaseType>>();
Thing<? extends MyBaseType> thing=createThing();
things.add(thing);
Then I'd figure out what T is later, when I had more information.
This all seems to come down to incomplete generic covariance in C# coupled with the lack of C# generic wildcards. (I still maintain it isn't an erasure issue.)
So what do I do? The only simple thing to do seems to follow Reinderien's answer and split out a non-generic base class.
(I wonder if in this non-generic base class I could have object getValue() and then use covariance in the subclass to return T getValue()? Ack, I'm tired of this---I'll leave that for another day.)

Difference between implicit and explicit implementation of C# interfaces [duplicate]

This question already has answers here:
C# Interfaces. Implicit implementation versus Explicit implementation
(13 answers)
Closed 7 years ago.
What's the difference between Explicitly implement the interface and Implement the interface.
When you derive a class from an interface, intellisense suggest you to do both.
But, what's the difference?
Another aspect of this:
If you implicitly implemented, it means that the interface members are accessible to users of your class without them having to cast it.
If it's explicitly implemented, clients will have to cast your class to the interface before being able to access the members.
Here's an example of an explicit implementation:
interface Animal
{
void EatRoots();
void EatLeaves();
}
interface Animal2
{
void Sleep();
}
class Wombat : Animal, Animal2
{
// Implicit implementation of Animal2
public void Sleep()
{
}
// Explicit implementation of Animal
void Animal.EatRoots()
{
}
void Animal.EatLeaves()
{
}
}
Your client code
Wombat w = new Wombat();
w.Sleep();
w.EatRoots(); // This will cause a compiler error because it's explicitly implemented
((Animal)w).EatRoots(); // This will compile
The IDE gives you the option to do either - it would be unusual to do both. With explicit implementation, the members are not on the (primary) public API; this is handy if the interface isn't directly tied to the intent of the object. For example, the ICustomTypeDescriptor members aren't all that helpful to regular callers - only to some very specific code, so there is no purpose having them on the public API causing mess.
This is also useful if:
there is a conflict between an interface's Foo method and your own type's Foo method, and they mean different things
there is a signature conflict between other interfaces
The typical example of the last point is IEnumerable<T>, which has a GetEnumerator() method at two levels in the interface hierarchy - it is common to implement the typed (IEnumerator<T>) version using implicit implementation, and the untyped (IEnumerator) version using explicit implementation.
Here's the difference in plain English:
Suppose you have an interface Machine, which has a function Run(), and another interface Animal which also has a function called Run(). Of course, when a machine runs, we're talking about it starting up, but when an animal runs, we're talking about it moving around. So what happens when you have an object, lets call it Aibo that is both a Machine and an Animal? (Aibo is a mechanical dog, by the way.) When Aibo runs, does he start up, or does move around? Explicitly implementing an interface lets you make that distinction:
interface Animal
{
void Run();
}
interface Machine
{
void Run();
}
class Aibo : Animal, Machine
{
void Animal.Run()
{
System.Console.WriteLine("Aibo goes for a run.");
}
void Machine.Run()
{
System.Console.WriteLine("Aibo starting up.");
}
}
class Program
{
static void Main(string[] args)
{
Aibo a = new Aibo();
((Machine)a).Run();
((Animal)a).Run();
}
}
The catch here is that I can't simply call a.Run() because both of my implementations of the function are explicitly attached to an interface. That makes sense, because otherwise how would the complier know which one to call? Instead, if I want to call the Run() function on my Aibo directly, I'll have to also implement that function without an explicit interface.
Explicit will put IInterfaceName. at the front of all of the interface implementations. It's useful if you need to implement two interfaces that contain names/signatures that clash.
More info here.
Explicitly implement puts the fully qualified name on the function name consider this code
public interface IamSam
{
int foo();
void bar();
}
public class SamExplicit : IamSam
{
#region IamSam Members
int IamSam.foo()
{
return 0;
}
void IamSam.bar()
{
}
string foo()
{
return "";
}
#endregion
}
public class Sam : IamSam
{
#region IamSam Members
public int foo()
{
return 0;
}
public void bar()
{
}
#endregion
}
IamSam var1;
var1.foo() returns an int.
SamExplicit var2;
var2.foo() returns a string.
(var2 as IamSam).foo() returns an int.
Here you go, directly from MSDN
The difference is that you can inherit a class from several interfaces. These interfaces may have identical Method signatures. An explicit implementation allows you to change your implementation according to which Interface was used to call it.
Explicit interface implementation, where the implementation is hidden unless you explicitly cast, is most useful when the interface is orthogonal to the class functionality. That is to say, behaviorally unrelated .
For example, if your class is Person and the interface is ISerializable, it doesn't make much sense for someone dealing with Person attributes to see something weird called 'GetObjectData' via Intellisense. You might therefore want to explicitly implement the interface.
On the other hand, if your person class happens to implement IAddress, it makes perfect sense to see members like AddressLine1, ZipCode etc on the Person instances directly (implicit implementation).

Categories

Resources