C# Generics: wildcards - c#

I'm new to the c# world, and I'm trying to wrap my head around generics. Here is my current problem:
public Interface IAnimal{
string getType();
}
public Interface IAnimalGroomer<T> where T:IAnimal{
void groom(T);
}
Now I want to have a dictionary that contains these animal groomers. How do I do that? In java, I could do something like this:
HashMap<String,IAnimalGroomer<?>> groomers = new HashMap<>();
Edit: Here is an example of what I'm trying to do:
public class Dog : IAnimal
{
public string GetType()
{
return "DOG";
}
public void ClipNails() { }
}
public class DogGroomer : IAnimalGroomer<Dog>
{
public void Groom(Dog dog)
{
dog.ClipNails();
}
}
public class Program
{
private List<IAnimalGroomer<IAnimal>> groomers = new List<IAnimalGroomer<IAnimal>>();
public void doSomething()
{
//THIS DOESN"T COMPILE!!!!
groomers.Add(new DogGroomer());
}
}
EDIT
I think my intentions were unclear in the original post. My ultimate goal is to make an AnimalGroomerClinic that employs different types of IAnimalGroomers. Then animal owners can drop off animals at the clinic, and the clinic can decide which groomer should take care of the animal:
public class AnimalGroomerClinic
{
public Dictionary<String, IAnimalGroomer> animalGroomers = new Dictionary<String,IAnimalGroomer>();
public void employGroomer(IAnimalGroomer groomer){
animalGroomers.add(groomer.getAnimalType(), groomer);
}
public void Groom(IAnimal animal){
animalGroomers[animal.getAnimalType()].Groom(animal);
}
}
I realize I could do this without using generics. But the generics allow me to write the IAnimalGroomer interface in such a way that it is tied (at compile time) to a specific instance of IAnimal. In addition, concrete classes of IAnimalGroomer don't need to cast their IAnimals all the time, since generics would force implementations to deal with one specific kind of animal. I have used this idiom before in Java, and I'm just wondering if there is a similar way to write it in C#.
Edit 2:
Lots of interesting discussion. I'm accepting an answer that pointed me to dynamic dispatching in the comments.

What you want is call site covariance, which is not a feature that C# supports. C# 4 and above support generic variance, but not call site variance.
However, that doesn't help you here. You want a dog groomer to be put in a list of animal groomers, but that can't work in C#. A dog groomer cannot be used in any context in which an animal groomer is needed because a dog groomer can only groom dogs but an animal groomer can also groom cats. That is, you want the interface to be covariant when it cannot be safely used in a covariant manner.
However your IAnimalGroomer<T> interface could be contravariant as it stands: an animal groomer can be used in a context in which a dog groomer is required, because an animal groomer can groom dogs. If you made IAnimalGroomer<T> contravariant by adding in to the declaration of T then you could put an IAnimalGroomer<IAnimal> into an IList<IAnimalGroomer<Dog>>.
For a more realistic example, think of IEnumerable<T> vs IComparer<T>. A sequence of dogs may be used as a sequence of animals; IEnumerable<T> is covariant. But a sequence of animals may not be used as a sequence of dogs; there could be a tiger in there.
By contrast, a comparer that compares animals may be used as a comparer of dogs; IComparer<T> is contravariant. But a comparer of dogs may not be used to compare animals; someone could try to compare two cats.
If that is still not clear then start by reading the FAQ:
http://blogs.msdn.com/b/csharpfaq/archive/2010/02/16/covariance-and-contravariance-faq.aspx
and then come back and ask more questions if you have them.

There are two interfaces, IEnumerable and IEnumerable<T> which are close to what you are trying to accomplish. So you can have a dictionary like Dictionary<string,IEnumerable> which can contain as values IEnumerable<int>, IEnumerable<string>, etc. The trick here is to derive IAnimalGroomer<T> from IAnimalGroomer, a non generic interface.
EDIT:
As an example, per your request, after creating an interface called IAnimalGroomer with:
public interface IAnimalGroomer{
}
, if you change the line that reads:
public interface IAnimalGroomer<T> where T:IAnimal{
to
public interface IAnimalGroomer<T> : IAnimalGroomer where T:IAnimal{
and the line that reads:
private List<IAnimalGroomer<IAnimal>> groomers = new List<IAnimalGroomer<IAnimal>>();
to
private List<IAnimalGroomer> groomers=new List<IAnimalGroomer>();
your code should compile and work.

I know this has been Lipperted but I still feel like answering. The List is a red herring here, it doesn't matter that you're using it.
The reason this doesn't work is because IAnimalGroomer<T> itself is not covariant, and it can't be made covariant explicitly because of the groom(T) method. It is illegal to cast IA<Derived> to IA<Base> in the general case, or in different words, generic interfaces are not covariant by default. The List<T>.Add method is what triggers a cast from DogGroomer (which is IAnimalGroomer<Dog>) to IAnimalGroomer<IAnimal>, but for example, this still won't work:
IAnimalGroomer<Dog> doggroomer = new DogGroomer(); // fine
IAnimalGroomer<IAnimal> animalgroomer = doggroomer; // invalid cast, you can explicitly cast it
// in which case it fails at run time
If this worked (so if IAnimalGroomer<T> was covariant), you could in fact also add a DogGroomer to your list, despite the List<T> not being covariant! That's why I said the list is a red herring.
The reason generic interface covariance isn't the default is because of type safety. I added Cat/CatGroomer classes to your code that are basically the same as the ones for dogs. Look at the main function and the comments in it.
public interface IAnimal
{
string getType();
}
public interface IAnimalGroomer<T> where T:IAnimal
{
void groom(T t);
}
public class Dog : IAnimal
{
public string getType() { return "DOG"; }
public void clipNails() { }
}
public class DogGroomer : IAnimalGroomer<Dog>
{
public void groom(Dog dog)
{
dog.clipNails();
}
}
public class Cat : IAnimal
{
public string getType() { return "CAT"; }
public void clipNails() { }
}
public class CatGroomer : IAnimalGroomer<Cat>
{
public void groom(Cat cat)
{
cat.clipNails();
}
}
public class Program
{
static void Main(string[] args)
{
// this is fine.
IAnimalGroomer<Dog> doggroomer = new DogGroomer();
// this is an invalid cast, but let's imagine we allow it!
IAnimalGroomer<IAnimal> animalgroomer = doggroomer;
// compile time, groom parameter must be IAnimal, so the following is legal, as Cat is IAnimal
// but at run time, the groom method the object has is groom(Dog dog) and we're passing a cat! we lost compile-time type-safety.
animalgroomer.groom(new Cat());
}
}
There are no sequences used, yet the code would still break type safety if it was legal.
This type of cast could be allowed, but the errors caused by it would happen at run-time, which I imagine was not desirable.
If you mark the type parameter T as "out", then you can cast A<Derived> into A<Base>. However, you can no longer have a method with T as an argument, which you do. But it eliminates the problem of trying to shove a Cat into a Dog.
IEnumerable<T> is an example of a covariant interface - it has no f(T) methods so the problem can't happen, unlike with your groom(T) method.

As Brian pointed out in comments above, maybe dynamic is the way to go here.
Check out the following code. You get the benefits of generics to tie down the API nicely and under the hoods you use dynamic to make things work.
public interface IAnimal
{
}
public class Dog : IAnimal
{
}
public class Cat : IAnimal
{
}
public class BigBadWolf : IAnimal
{
}
//I changed `IAnimalGroomer` to an abstract class so you don't have to implement the `AnimalType` property all the time.
public abstract class AnimalGroomer<T> where T:IAnimal
{
public Type AnimalType { get { return typeof(T); } }
public abstract void Groom(T animal);
}
public class CatGroomer : AnimalGroomer<Cat>
{
public override void Groom(Cat animal)
{
Console.WriteLine("{0} groomed by {1}", animal.GetType(), this.GetType());
}
}
public class DogGroomer : AnimalGroomer<Dog>
{
public override void Groom(Dog animal)
{
Console.WriteLine("{0} groomed by {1}", animal.GetType(), this.GetType());
}
}
public class AnimalClinic
{
private Dictionary<Type, dynamic> groomers = new Dictionary<Type, dynamic>();
public void EmployGroomer<T>(AnimalGroomer<T> groomer) where T:IAnimal
{
groomers.Add(groomer.AnimalType, groomer);
}
public void Groom(IAnimal animal)
{
dynamic groomer;
groomers.TryGetValue(animal.GetType(), out groomer);
if (groomer != null)
groomer.Groom((dynamic)animal);
else
Console.WriteLine("Sorry, no groomer available for your {0}", animal.GetType());
}
}
And now you can do:
var animalClinic = new AnimalClinic();
animalClinic.EmployGroomer(new DogGroomer());
animalClinic.EmployGroomer(new CatGroomer());
animalClinic.Groom(new Dog());
animalClinic.Groom(new Cat());
animalClinic.Groom(new BigBadWolf());
I'm not sure if this is somewhat what you were looking for. Hope it helps!

Here is some code that works. I've added some classes and switch AnimalGroomer to be an abstract class not an interface:
class Program
{
static void Main(string[] args)
{
var dict = new Dictionary<string, IGroomer>();
dict.Add("Dog", new DogGroomer());
// use it
IAnimal fido = new Dog();
IGroomer sample = dict["Dog"];
sample.Groom(fido);
Console.WriteLine("Done");
Console.ReadLine();
}
}
// actual implementation
public class Dog : IAnimal { }
public class DogGroomer : AnimalGroomer<Dog>
{
public override void Groom(Dog beast)
{
Console.WriteLine("Shave the beast");
}
}
public interface IAnimal {
}
public interface IGroomer
{
void Groom(object it);
}
public abstract class AnimalGroomer<T> : IGroomer where T : class, IAnimal
{
public abstract void Groom(T beast);
public void Groom(object it)
{
if (it is T)
{
this.Groom(it as T);
return;
}
throw new ArgumentException("The argument is not a " + typeof(T).GetType().Name);
}
}
Please let me know if there are any questions

From my understanding, you cannot put the type constraints in the parameter in this case. which means you might need to do the boxing and unboxing. you might need to use a normal interface.
public interface IAnimal{
string GetType();
}
public interface IAnimalGroomer{
void Groom(IAnimal dog);
}
public class Dog : IAnimal
{
public string GetType()
{
return "DOG";
}
public void ClipNails()
{
}
}
public class DogGroomer : IAnimalGroomer
{
public void Groom(IAnimal dog)
{
if (dog is Dog)
{
(dog as Dog).ClipNails();
}
else {
// something you want handle.
}
}
}
public class Program
{
private List<IAnimalGroomer> groomers = new List<IAnimalGroomer>();
public void doSomething()
{
groomers.Add(new DogGroomer());
}
}
Or maybe you need to have another technical design for solving your problem

I'm adversed to using dynamic, because it has a runtime cost to it.
One simpler solution, uses a Dictionary<string, object> in which you can safely store any IAnimalGroomer<T>.
public class AnimalGroomerClinic {
public Dictionary<string, object> animalGroomers = new Dictionary<string, object>();
public void employGroomer<T>(IAnimalGroomer<T> groomer) where T : IAnimal {
animalGroomers.Add(groomer.getAnimalType(), groomer);
}
public void Groom<T>(T animal) where T : IAnimal {
// Could also check here if the 'as' operator returned null,
// which might happen if you don't have the specific groomer
(animalGroomers[animal.getAnimalType()] as IAnimalGroomer<T>).groom(animal);
}
}
Now, this requires a cast, which you might say is unsafe. But you know it's safe due to encapsulation. If you put an IAnimalGroomer<Dog> into the hashmap under the key "dog". And request it again with the key "dog", you know it will still be an IAnimalGroomer<Dog>.
Just like with the java equivalent:
class AnimalGroomerClinic {
public Map<String, Object> animalGroomers = new HashMap<>();
public <T extends IAnimal> void employGroomer(IAnimalGroomer<T> groomer) {
animalGroomers.put(groomer.getAnimalType(), groomer);
}
#SuppressWarnings("unchecked")
public <T extends IAnimal> void Groom(T animal) {
((IAnimalGroomer<T>) animalGroomers.get(animal.getAnimalType())).groom(animal);
}
}
Which still requires an unchecked cast (even if you change Object to IAnimalGroomer<?>). The point is that you're trusting your encapsulation enough to do an unchecked cast.
It doesn't really add anything to have IAnimalGroomer<?> instead of Object in terms of type safety. Because you're encapsulation already ensures more.
It could be done for readability, to indicated what kind of objects the map holds by having IAnimalGroomer<T> implement a stub interface:
public interface IAnimalGroomerSuper {
// A stub interface
}
public interface IAnimalGroomer<T> : IAnimalGroomerSuper where T : IAnimal {...}
Then the dictionary could be:
public Dictionary<string, IAnimalGroomerSuper> animalGroomers = ...;

The point is to use a non-generic interface behind the scenes to limit the types, but only expose the generic version.
void Main()
{
var clinic = new AnimalClinic();
clinic.Add(new CatGroomer());
clinic.Add(new DogGroomer());
clinic.Add(new MeanDogGroomer());
clinic.Groom(new Cat()); //Purr
clinic.Groom(new Dog()); //Woof , Grrr!
}
public interface IAnimal {}
public interface IGroomer {}
public class Dog : IAnimal
{
public string Woof => "Woof";
public string Growl => "Grrr!";
}
public class Cat : IAnimal
{
public string Purr => "Purr";
}
public interface IGroomer<T> : IGroomer where T : IAnimal
{
void Groom(T animal);
}
public class DogGroomer : IGroomer<Dog>
{
public void Groom(Dog dog) => Console.WriteLine(dog.Woof);
}
public class MeanDogGroomer : IGroomer<Dog>
{
public void Groom(Dog dog) => Console.WriteLine(dog.Growl);
}
public class CatGroomer : IGroomer<Cat>
{
public void Groom(Cat cat) => Console.WriteLine(cat.Purr);
}
public class AnimalClinic
{
private TypedLookup<IGroomer> _groomers = new TypedLookup<IGroomer>();
public void Add<T>(IGroomer<T> groomer) where T : IAnimal
=> _groomers.Add<T>(groomer);
public void Groom<T>(T animal) where T : IAnimal
=> _groomers.OfType<T, IGroomer<T>>().ToList().ForEach(g => g.Groom(animal));
}
public class TypedLookup<T> : Dictionary<Type, IList<T>>
{
public void Add<TType>(T item)
{
IList<T> list;
if(TryGetValue(typeof(TType), out list))
list.Add(item);
else
this[typeof(TType)] = new List<T>{item};
}
public IEnumerable<TRet> OfType<TType, TRet>() => this[typeof(TType)].Cast<TRet>();
public TRet First<TType, TRet>() => this[typeof(TType)].Cast<TRet>().First();
}

Related

C# generic inheritance, base class casting

I wanted to make the following inheritance with included generics, but the final cast
a as A<XBase> always results in null, because the cast is not valid. Could anybody elaborate on why this cast would be invalid, as well as maybe a solution to this problem.
public class XBase {}
public interface A<T> where T : XBase
{
//Edited
void Method(T param);
}
public class Implementor : A<Implementor.ImplementorX >
{
public class ImplementorX : XBase {public int a;}
//Edited
void Method(ImplementorX param) {}
}
public class HelloWorld
{
public static void Main(string[] args)
{
var a = new Implementor();
var castRes = a as A<XBase>;
Console.WriteLine(castRes != null);
}
}
see live example https://rextester.com/BTNVT61833
EDITED: Added a method to interface A<T> bc else it could be solved with #DavidG's response
If you make an explicit cast:
var castRes = A<XBase>(a);
then you will see the following error:
Unable to cast object of type '' to type '`
Why? In my view, it is better to understand using real world example. I've renamed classes based on this explanation. There are comments which maps explanations to your classes in question.
Abstractions:
// XBase
public class Animal { }
// class ImplementorX : XBase {public int a;}
public class Bird : Animal
{
public string WingColor { get; set; }
}
// interface A<T> where T : XBase
public interface IHat<T> where T : Animal
{
void Hide(T param);
T Pull();
}
Concrete implementations:
// class Implementor : A<Implementor.ImplementorX >
public class Peacock : IHat<Bird>
{
// void Method(ImplementorX param) {}
void IHat<Bird>.Hide(Bird param)
{ }
public Bird Pull()
{ }
}
and how it can be called:
public static void Main(string[] args)
{
Peacock peacockHat = new Peacock();
IHat<Animal> animalHat = (IHat<Animal>) peacockHat; // runtime error 'Unable to cast
// object of type 'HelloWorld.Peacock' to type 'HelloWorld.IHat`1
// because
animalHat.Hide(new Dolphin()); // Hide a dolphin in a peacock hat?
}
So we cannot hide hat of Peacock from Dolphin. It is not okay. CLR prevents us from making inappropriate actions.
In short:
In short, imagine you have two animals such as Wolf and Sheep. And these classes implements IAnimal interface:
public interface IAnimal
{ }
public class Wolf: IAnimal
{ }
public class Sheep : IAnimal
{ }
So Sheep, Wolf classes implement the inherited interface IAnimal:
IAnimal
/ \
/ \
Sheep Wolf
And then these animals can be put in cage:
public class Cage<T> where T : IAnimal
{
public void Put(T animal)
{ }
}
Then you create a cage for Sheep. After that somebody wants to cast Sheep cage to IAnimal:
Cage<Sheep> sheepCage = new Cage<Sheep>();
sheepCage.Put(new Sheep());
Cage<IAnimal> animalCage = (Cage<Wolf>)sheepCage; // compile error
// if there were no error, then you will be able to do:
animalCage.Put(new Wolf()); // it is not good idea

Can i call a method that takes IEnumerable<Baseclass<superclass>> with IEnumerable<Derivedclass<subclass>>

I have some code that's equivalent to this (though this is a simplification):
namespace AnimalHospital
{
public class Animal { }
public class Dog : Animal { }
public class Cat : Animal { }
public interface Vet<T> where T : Animal
{
void takeCareOf(T animal);
}
public abstract class SpecializedDogVet<T> : Vet<T> where T : Dog
{
public abstract void takeCareOf(T dog);
}
public abstract class SpecializedCatVet<T> : Vet<T> where T : Cat
{
public abstract void takeCareOf(T cat);
}
public class AnimalHospital
{
public IList<SpecializedCatVet<Cat>> CatVets = new List<SpecializedCatVet<Cat>>();
public IList<SpecializedDogVet<Dog>> DogVets = new List<SpecializedDogVet<Dog>>();
private void treatSickAnimal(IEnumerable<Vet<Animal>> vets, Animal patient)
{
foreach(var vet in vets)
{
vet.takeCareOf(patient);
}
}
public void treatSickCat(Cat cat)
{
treatSickAnimal(CatVets, cat);
}
public void treatSickDog(Dog dog)
{
treatSickAnimal(DogVets, dog);
}
}
}
I get an error, telling me that conversion from:
IList<SpecializedCatVet<Cat>> to IEnumerable<Vet<Animal>> is not possible. How can this be? Before this they were nonegeneric, and i had some other problems, as i could not override the vet interfaces takeCareOf method. I had expected that as IEnumerable of Animal can easily be instantiated with a list of Dog, the same would be the case with parsing a collection of generics as long as their type parameter is a derirative of the required type. This is not the case though, and I seem unable to figure out why, or how to do this properly.
Thanks for reading.
UPDATE: I'm Accepting JLRishe's answer, makes perfect sense. Thank you very much.
This is not allowed, because if it were allowed, you could something like this:
var cat = new Cat();
treatSickAnimal(DogVets, cat);
And essentially try to force dog vets to treat a cat.
You can remedy this by making your methods generic on the animal parameter:
private void treatSickAnimal<T>(IEnumerable<Vet<T>> vets, T patient) where T : Animal
{
foreach (var vet in vets)
{
vet.takeCareOf(patient);
}
}
This should allow your code to compile correctly and ensure that you don't try to force any dog vets to treat cats.
Side note note - unless you plan on having specialized types (subclasses) of Dog and Cat and vets that are specialized for those subclasses, you can simplify the definition of SpecializedDogVet and SpecializedCatVet to be like this:
public abstract class SpecializedDogVet : Vet<Dog>
{
public abstract void takeCareOf(Dog dog);
}
public abstract class SpecializedCatVet : Vet<Cat>
{
public abstract void takeCareOf(Cat cat);
}
You would then refer to the types like this:
public IList<SpecializedCatVet> CatVets = new List<SpecializedCatVet>();
public IList<SpecializedDogVet> DogVets = new List<SpecializedDogVet>();
You cant because your Vet<T> interface is currently invariant, notice you can make it contravariant by specifying that it is input parameter like so:
public interface Vet<in T> where T : Animal
{
void takeCareOf(T animal);
}
This is possible because everywhere T is used as input parameter.
In order your code to compile you can do what #JLRishe said, or you can change your logic and make T output parameter, but in order to do that you need to change your Vet implementation so everywhere T is used it needs to be in position of output just an example:
public interface Vet<out T> where T : Animal
{
T takeCareOf();
}
So in conclusion, you can pass base class to interfaces or delegates where they have type parameters defined as output and you can pass more derived classes when type parameters are defined as input.
This is actually AMAZING article for covariance and contravariance if I got you hooked you should definitely check it http://tomasp.net/blog/variance-explained.aspx/

C# Passing current generic class instance to other class

lately I started to learn generics. I run into trouble with storing references to generic classes instances. As you can see, my class ListHandler can store references to specific type of BaseClass. I would love to register BaseClass instances by themselves, which is why I wanted to guarantee that they will use BaseParamClass by adding 'where'. Anyway - it does not compile.'This', does not know that T is actually BaseClassParam even with 'where' keyword in class. I don't know what is wrong here and I couldn't find answer anywhere. I would be grateful for tips/guides/solutions.
public class ListHandler
{
private List<BaseClass<BaseParamClass>> list;
public ListHandler()
{
list = new List<BaseClass<BaseParamClass>>();
}
public void Register(BaseClass<BaseParamClass> param)
{
list.Add(param);
}
}
public class BaseClass<T> where T : BaseParamClass
{
private ListHandler listHandler;
public T Param { get; private set; }
public BaseClass(ListHandler listHandler)
{
this.listHandler = listHandler;
listHandler.Register(this); //throws error
}
}
Why don't you make ListHandler generic as well?
public class ListHandler<T>
{
private List<BaseClass<T>> list;
public ListHandler()
{
list = new List<BaseClass<T>>();
}
public void Register(BaseClass<T> param)
{
list.Add(param);
}
}
public class BaseClass<T>
{
private ListHandler<T> listHandler;
public T Param { get; private set; }
public BaseClass(ListHandler<T> listHandler)
{
this.listHandler = listHandler;
listHandler.Register(this);
}
}
Also, it seems strange to me to have BaseClass<T> contain a reference to a class that has a reference to BaseClass<T> itself.
I have another option for you.
Let's split the BaseClass<T> class into two with a non-generic base, like so:
public class BaseClass
{
protected ListHandler listHandler;
public BaseClass(ListHandler listHandler)
{
this.listHandler = listHandler;
}
}
public class BaseClass<T> : BaseClass where T : BaseParamClass
{
public T Param { get; private set; }
public BaseClass(ListHandler listHandler)
: base(listHandler)
{
listHandler.Register(this); // Compiles nicely! Yay!
}
}
Now, the list inside ListHandler can be defined as private List<BaseClass> list;. That means there is no problem adding any BaseClass item to the list. We also can then define two methods for registering and fetching generic versions of the BaseClass<T> from the ListHandler. It would look like this:
public class ListHandler
{
private List<BaseClass> list;
public ListHandler()
{
list = new List<BaseClass>();
}
public void Register<T>(BaseClass<T> param) where T : BaseParamClass
{
list.Add(param);
}
public BaseClass<T> Fetch<T>() where T : BaseParamClass
{
return list.Select(x => x as BaseClass<T>).Where(x => x != null).FirstOrDefault();
}
}
So, given a class public class FooParam : BaseParamClass { } I can write this code:
ListHandler listHandler = new ListHandler();
BaseClass<FooParam> baseClass = new BaseClass<FooParam>(listHandler);
BaseClass<FooParam> baseClass2 = listHandler.Fetch<FooParam>();
Console.WriteLine(object.ReferenceEquals(baseClass, baseClass2));
The result from this code is True is written to the console - which means I can successfully fetch the instance of BaseClass<FooParam> from the ListHandler.
Why your code doesn't compile
In order to fully understand why your code doesn't compile, you'll have to dive into covariance and contravariance, which is a big topic and hard to explain in an SO answer. It can be especially confusing if you've gotten to a point where inheritance polymorphism is second nature to you; the rules are just different enough to be make your head hurt.
Here is what is confusing--
You're used to doing this:
object a = new String(...);
But generics don't let you do this!
List<object> c = new List<string>(); //Compiler error
That's because those two Lists are not related the same way that object and string are related. One does not inherit from the other. Rather, they are different variants of a generic type definition. In the generic world, you can't assign one to the other. The same is true of this:
void Foo<T>() where T: BaseParamClass
{
BaseClass<BaseParamClass> a = new BaseClass<T>(); //Compiler error
}
In this example, T could be BaseParamClass or one of its derived types. They are not the same type. So to remain type-safe, the compiler has to disallow this assignment, and your Register call, which has the same type mismatch.
Standard ways around this
You need a covariant interface. These allow assignment from derived to base. So for example, while this is still illegal:
List<object> a = new List<string>(); //Compiler error
This is totally fine:
IEnumerable<object> e = new List<string>(); //Is OK
Because IEnumerable was declared to be covariant, like this:
interface IEnumerable<out T>
Which means it is can be assigned in this way. It works because using out also adds a compiler constraint to the interface: it can be used to retrieve stuff...
interface IEnumerable<out T>
{
T Item[int index];
}
...but it cannot accept anything:
interface IEnumerable<out T>
{
Add(T item); //Compiler error
}
These constraints are what allow generics to provide early-bound type safety while still allowing certain forms of (non-inheritance) polymorphism.
What I'd suggest
Based on your comment, it sounds like you just need a container (a stack, apparently) that can hold references to these BaseClass<T> instances. If you are following separation of concerns, the stack doesn't need to actually do anything with the T, other than store it and retrieve it, and to allow it to register itself.
Since that is a separate concern, make a separate interface.
And in the interest of keeping things simple, maybe avoid using generics completely for this bit.
One way to do it--
Create an interface that allows access to everything the stack needs to know about an item it is containing. For example, if the stack contains popups of various kinds, you may want to expose the popup's title.
interface IStackable
{
string Title { get; set; }
}
Now use it like this:
public class ListHandler
{
private readonly Dictionary<string, IStackable> list;
public ListHandler()
{
list = new Dictionary<string, IStackable>();
}
public void Register(IStackable item)
{
list.Add(item.Title, item);
}
}
public class BaseClass<T> : IStackable where T : BaseParamClass
{
private ListHandler listHandler;
public T Param { get; private set; }
public BaseClass(ListHandler listHandler)
{
this.listHandler = listHandler;
listHandler.Register(this);
}
public string Title { get; set; }
}
Unless there is some other requirement, you shouldn't need to make it any more complicated than that.
All you really need to do is add an interface. This works:
public class BaseParamClass
{
}
public class ListHandler
{
private List<IBase<BaseParamClass>> list;
public ListHandler()
{
list = new List<IBase<BaseParamClass>>();
}
public void Register(IBase<BaseParamClass> param)
{
list.Add(param);
}
}
public interface IBase<T> where T : BaseParamClass
{
T Param {get; }
}
public class BaseClass : IBase<BaseParamClass>
{
private ListHandler listHandler;
public BaseParamClass Param { get; private set; }
public BaseClass(ListHandler listHandler)
{
this.listHandler = listHandler;
listHandler.Register(this);
}
}
Working code on DotNetFiddle

C# - using extension methods to provide default interface implementation

I'm just learning about C# extension methods, and was wondering if I can use it to provide a default implementation for an interface.
Say:
public interface Animal {
string MakeSound();
}
public static string MakeSound(this Animal) {
return "";
}
Then
public class Dog : Animal {
string MakeSound() {
return "Bark";
}
}
public class Porcupine : Animal {
}
And last:
Animal dog = new Dog();
Animal porcupine = new Porcupine();
Print(dog.MakeSound());
Print(porcupine.MakeSound());
I'd like the porcupine and any other animals that have not explicitly implemented MakeSound to use the default extension method that returns an empty string, but dog and any animal that does have an explicit implementation return its own implementation such as "Bark".
So my questions:
1. Is this doable?
2. If not, is there any other way to implement default behavior for an interface?
Abstract class instead of interface is not an option because C# doesn't support multiple inheritance and my classes are inheriting behavior of another class.
I'd generally recommend a base class, however, if that's out, you can do something like this:
public interface IAnimal { }
public interface INoisyAnimal : IAnimal {
string MakeSound();
}
public static class AnimalExtensions {
public static string MakeSound(this IAnimal someAnimal) {
if (someAnimal is INoisyAnimal) {
return (someAnimal as INoisyAnimal).MakeSound();
}
else {
return "Unknown Noise";
}
}
}
public class Dog : INoisyAnimal {
public string MakeSound() {
return "Bark";
}
}
public class Porcupine : IAnimal { }
This makes every IAnimal look like a INoisyAnimal even if it isn't really one. For example:
IAnimal dog = new Dog();
IAnimal porcupine = new Porcupine();
Console.WriteLine(dog.MakeSound()); // bark
Console.WriteLine(porcupine.MakeSound()); // Unknown Noise
However, this still isn't an actual implementation of the interface. Notice that despite appearances
Console.WriteLine(porcupine is INoisyAnimal); // false
Another option might be to create a wrapper to extend your base class when new functionality is needed:
public class NoisyAnimalWrapper : INoisyAnimal {
private readonly IAnimal animal;
public NoisyAnimalWrapper(IAnimal animal) {
this.animal = animal;
}
public string MakeSound() {
return "Unknown Noise";
}
}
public static class AnimalExtensions {
public static INoisyAnimal Noisy(this IAnimal someAnimal) {
return someAnimal as INoisyAnimal ??
new NoisyAnimalWrapper(someAnimal);
}
}
Then you can create a INoisyAnimal from any IAnimal whenever you need to:
INoisyAnimal dog = new Dog();
INoisyAnimal porcupine = new Porcupine().Noisy();
Console.WriteLine(dog.MakeSound()); // bark
Console.WriteLine(porcupine.MakeSound()); // Unknown Noise
You could also make the wrapper generic (e.g. NoisyAnimal<T> where T : IAnimal, new) and get rid of the extension method altogether. Depending on your actual use case, this may be preferable to the previous option.
I don't know exactly what is your real case or if you are just experimenting but, if only some animals are noisy, then it might a good case for Interface segregation.
For example:
public class Dog : IAnimal, INoisy
{
public string MakeSound()
{
return "Bark";
}
}
public class Porcupine : IAnimal
{
}
Then, you will only call MakeSound or objects that are actually noisy.
How about something like this? It allows you to avoid having a base class, and you can do what you had in mind, right?
public interface Animal
{
// Fields
string voice { get; }
}
public static class AnimalHelper
{
// Called for any Animal
public static string MakeSound(this Animal animal)
{
// Common code for all of them, value based on their voice
return animal.voice;
}
}
public class Dog : Animal
{
public string voice { get { return "Woof!"; } }
}
public class Purcupine : Animal
{
public string voice { get { return ""; } }
}

Abstract method with strongly typed return type

Consider the following classes :
public abstract class Animal
{
public abstract Animal GiveBirth();
}
public class Monkey : Animal
{
public override Animal GiveBirth()
{
return new Monkey();
}
}
public class Snake : Animal
{
public override Animal GiveBirth()
{
return new Snake();
}
}
//That one doesnt makes sense.
public class WeirdHuman: Animal
{
public override Animal GiveBirth()
{
return new Monkey();
}
}
I'm searching a way to enforce the return types of the overrided GiveBirth method so that it always returns the actual class type, so that no WeirdHuman can give birth to a Monkey.
I feel like the answer is about generic types, but I can't see how I can do that.
Exemple of the expected result :
public abstract class Animal
{
public abstract /*here a way to specify concrete type*/ GiveBirth();
}
public class Monkey : Animal
{
public override Monkey GiveBirth() //Must returns an actual Monkey
{
return new Monkey();
}
}
"Absolutely impossible" may be an answer, if clearly explained.
This is co-variant returns and is not supported by C#. I lament this daily. The best you can hope to do to get around it is to use a generic return type and specify a where condition on the generic type, but this can also cause you to run in to other issues down the road with matching generic parameter requirements.
public abstract class Animal<TBirthType> where TBirthType : Animal<TBirthType>
{
public abstract TBirthType GiveBirth();
}
public class Monkey<TBirthType> : Animal<TBirthType> where TBirthType : Monkey<TBirthType>
{
public override TBirthType GiveBirth()
{
return new Monkey<Monkey>();
}
}
Alternately, if you don't need any further inheritance, you can close the generic.
public class Monkey : Animal<Monkey>
{
public override Monkey GiveBirth()
{
return new Monkey();
}
}
Note that covariance alone is still not enough to ensure that no misbehaving derived type can be formed, but it will allow for the type of the return to be specified as the type being used. There still wouldn't be a way to lock it down from the abstract class though. You could perhaps manage a runtime check via reflection from a method implemented at the base level that would check type at runtime, but this could also be very messy.
As far as I know, there is no clean way to support this purely in a single class hierarchy. Using recurring generic type parameters e.g.
public class Animal<T> where T : Animal<T> { }
may be acceptable if you control the entire hierarchy, and can therefore rule out classes like
public class WierdHuman<Monkey> { }
What you really want is something like Haskell's typeclasses, where you can abstract over the concrete type of the class itself. The closest you can get in C# is to define a surrogate object which implements the required functionality, and then pass that around wherever you require it.
In your case, this means creating an interface for giving birth, and implementing it for each concrete animal type.
Your methods which require this functionality then need an extra parameter for the 'typeclass instance'. These methods can restrict the generic animal type to be the same:
public interface ISpawn<T> where T : Animal
{
public T GiveBirth();
}
public void Populate<T>(T parent, ISpawn<T> spawn) where T : Animal
{
}
You can do something like this, which forces the implementers of Animal<T> to implement an Animal<T> GiveBirth() method which returns the same type as the type parameter, which itself is constrained to be a kind of animal.
That's not quite what you want, but just so you can see:
public abstract class Animal<T> where T: Animal<T>
{
public abstract Animal<T> GiveBirth();
}
public class Monkey: Animal<Monkey>
{
public override Animal<Monkey> GiveBirth()
{
return new Monkey();
}
}
public class Snake: Animal<Snake>
{
public override Animal<Snake> GiveBirth()
{
return new Snake();
}
}
public class WeirdHuman: Animal<WeirdHuman>
{
public override Animal<WeirdHuman> GiveBirth()
{
return new Monkey(); // Won't compile of course.
}
}
If you comment out the public override Animal<Monkey> GiveBirth() methods, you'll see that the compiler complains and says something like:
Error 1 'ConsoleApplication1.Monkey' does not implement inherited abstract member 'ConsoleApplication1.Animal.GiveBirth()'
Unfortunately, you must declare the classes using the SomeKindOfAnimal: Animal<SomeKindOfAnimal> syntax, but maybe this will work for you.
(Also see this thread.)
Alas, this doesn't quite work because it allows you to do this:
public class Monkey: Animal<WeirdHuman>
{
public override Animal<WeirdHuman> GiveBirth()
{
return new WeirdHuman();
}
}
In other words, it constrains the type parameter to be a kind of animal, and it also constrains the return type of GiveBirth() to be the same as the type parameter; but that's all it does. In some cases this is enough, but probably not for your purposes.
Still, perhaps this approach is worth knowing about.
If you have an situation where your base class cannot be generic for various reasons, this method might be useful:
abstract class Animal {
}
interface ICanGiveBirth<T> {
T GiveBirth();
}
static class CanGiveBirthHelper {
public static T GiveBirth<T>(this T v) where T: ICanGiveBirth<T> => v.GiveBirth();
}
class Monkey : Animal, ICanGiveBirth<Monkey> {
public Monkey GiveBirth() {
throw new NotImplementedException();
}
}
class Snake : Animal, ICanGiveBirth<Snake> {
public Snake GiveBirth() {
throw new NotImplementedException();
}
}
If you are unable to add interface to your sub classes, and still unable to add generics to the Base type this method might be useful:
(Unfortunately you cannot make the GiveBirthImpl protected, since the helper class is not allowed to be inside the base class)
abstract class Animal {
public abstract T GiveBirthImpl<T>() where T:Animal;
}
static class CanGiveBirthHelper {
public static T GiveBirth<T>(this T v) where T: Animal => v.GiveBirthImpl<T>();
}
class Monkey : Animal {
public override T GiveBirthImpl<T>() {
throw new NotImplementedException();
}
}
class Snake : Animal {
public override T GiveBirthImpl<T>() {
throw new NotImplementedException();
}
}
In both cases, this will work as expected:
class Tester
{
Monkey TestIt() => new Monkey().GiveBirth();
}

Categories