I'm trying to make food for my IAnimals using a FoodFactory and have a large List<IAnimal> of Dogs and Foxs etc. Ideally, I would pass in an IAnimal and the FoodFactory would return the right food but I am not sure how to do this.
interface IAnimal {
void MakeNoise();
}
public sealed class Dog : IAnimal {
public void MakeNoise() { Console.WriteLine("Woof woof"); }
}
public sealed class Fox : IAnimal {
public void MakeNoise() { Console.WriteLine("What does the fox say?"); }
}
public static class FoodFactory {
public static void Create(Dog dog) {
Console.WriteLine("return dog food");
}
public static void Create(Fox fox) {
Console.WriteLine("return fox food");
}
}
and here's my caller code:
var myList = new List<IAnimal> { new Dog(), new Fox() };
foreach (var animal in myList)
{
FoodFactory.Create(animal); // Sadly, this doesn't work
}
Is there a 'proper' way to do this? All I can think of is a load of if statements like:
if (animal is Dog) { FoodFactory.Create(animal as Dog); }
I have a lot of animals and I'd much rather the computer work out which one it's dealing with than me! Thank you.
UPDATE
Thank you to all that have posted. I went with Xinchao's answer because it was most applicable in my context; it didn't affect my animal classes and allowed the type to be resolved at runtime without me checking all the animal types. There were three helpful answers which would have worked (e.g. using visitor pattern) but they weren't quite applicable in my context as I don't want to change/extend my animals.
The reason you are having this problem is the so-called overload resolution happens at compile time instead of run-time.
There are a couple of ways to solve it:
Using a bunch of if-else-if statements is certainly one way, although you can write it prettier.
With .Net 4.0 or above, you can use to "dynamic" keyword to delay the overload resolution to run-time. It has a performance penalty, but it achieves accurately what you need:
public static class FoodFactory {
public static void Create(dynamic animal) {
InternalCreate (animal);
}
private static void InternalCreate (Dog dog) {
Console.WriteLine("return dog food");
}
private static void InternalCreate (Fox fox) {
Console.WriteLine("return fox food");
}
}
To add a bit more type safety, you might consider to do something like:
public static class FoodFactory {
public static void Create(IAnimal animal) {
Dispatch (animal);
}
private static void Dispatch (dynamic animal) {
InternalCreate (animal);
}
private static void InternalCreate (Dog dog) {
Console.WriteLine("return dog food");
}
private static void InternalCreate (Fox fox) {
Console.WriteLine("return fox food");
}
}
Your FoodFactory does need to know what kind of animal its feeding, but I would imagine that the animal itself knows what kind of food it wants to eat. What if IAnimal provided that?
interface IAnimal {
void MakeNoise();
FoodType FavoriteFood { get; }
}
public sealed class Dog : IAnimal {
public void MakeNoise() { Console.WriteLine("Woof woof"); }
public FoodType FavoriteFood { get { return FoodType.DogFood; } }
}
public sealed class Fox : IAnimal {
public void MakeNoise() { Console.WriteLine("What does the fox say?"); }
public FoodType FavoriteFood { get { return FoodType.WhatTheFoxEats; } }
}
Now your FoodFactory has the information it needs to build food:
public static class FoodFactory {
public static IFood Create(IAnimal animal) {
// animal.FavoriteFood tells you what food to make
}
}
Maybe FavoriteFood actually returns an instance of food, and the factory just delegates to that? Maybe the factory maintains a mapping or some other logic of the enum above to actual food instances? Maybe some other way? (Or maybe you just output to the console like you already are instead of returning an object like I'm trying to do, in which case the animals can just write to the console and the factory still doesn't need to know anything else about the animal.) In any event, the factory's relationship to the animal is now polymorphically defined.
I think you need to modify your Create method in FoodFactory class to accept IAnimal as a parameter instead. You would also need to have a method declaration for FavFood or whatever you want to call it in the Interface which would get specific implementation from classes (Dogs, Fox) that inherits the Interface. Then in a factory class you could supply any animal of type IAnimal and have a method that invokes Animal specific FavFood method.
interface IAnimal
{
void FavFood();
}
public sealed class Dog : IAnimal
{
public void FavFood() { Console.WriteLine("Me loves dog food. Woof woof."); }
}
public sealed class Goat : IAnimal
{
public void FavFood() { Console.WriteLine("Me loves goat food. myaaa.."); }
}
public static class FoodFactory
{
public static void Create(IAnimal animal)
{
animal.FavFood();
}
}
And when you call it, you would do
var animals = new List<IAnimal> { new Dog(), new Fox() };
foreach (var animal in animals)
{
FoodFactory.Create(animal);
}
Did I answer what you were looking for? If not, let me know where I missed it...
Another alternative would be to use the visitor pattern:
using System;
using System.Collections.Generic;
public interface IAnimalVisitor
{
void Visit(Dog dog);
void Visit(Fox fox);
}
public class FeedingPersonnel : IAnimalVisitor
{
public void Visit(Dog dog)
{
Console.WriteLine("return dog food");
}
public void Visit(Fox fox)
{
Console.WriteLine("return fox food");
}
}
//public class Veterinarian : IAniamalVisitor { ... } (if you need it)
interface IAnimal
{
void Accept( IAnimalVisitor visitor);
void MakeNoise();
}
public sealed class Dog : IAnimal {
public void Accept( IAnimalVisitor visitor) { visitor.Visit(this); }
public void MakeNoise() { Console.WriteLine("Woof woof"); }
}
public sealed class Fox : IAnimal {
public void Accept( IAnimalVisitor visitor) { visitor.Visit(this); }
public void MakeNoise() { Console.WriteLine("What does the fox say?"); }
}
public class Test
{
public static void Main()
{
var myList = new List<IAnimal> { new Dog(), new Fox() };
var feeder = new FeedingPersonnel();
foreach (var animal in myList)
{
animal.Accept(feeder);
}
}
}
This method avoids casting and also provides you the means to add another types of visitors. With the downside that you have to provide Visit once for each new Animal and add a new method to the IAnimalVisitor and define it in each visitor implementer whenever a new Animal is added.
Depending on you actual situation this might be acceptable (or not).
Related
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
As per my understanding, We can use factory if we have same method implemented by subclasses, something like this
interface IAnimal
{
void Eat();
}
class Bird : IAnimal
{
public void Eat()
{
// bird eats grain
}
}
class Tiger : IAnimal
{
public void Eat()
{
// Tiger eats meat
}
}
our factory
class AnimalFactory
{
public IAnimal GetInstance(int type)
{
// dependind on type we can return
// animal
}
}
but what if we have another different method in the subclasses like Fly() in Bird class and Walk() in Tiger class?
class Bird : IAnimal
{
public void Eat()
{
// bird eats grain
}
public void Fly()
{
}
}
class Tiger : IAnimal
{
public void Eat()
{
// Tiger eats meat
}
public void Walk()
{
}
}
What is the best way to implement? I think, since subclasses do not implement completely one interface, so we should not use a factory design pattern? Of course we can still use and client can use Fly() and Walk() method by casting it back to the respective classes.
But my question is, is this still a valid use case for implementing factory design pattern?
Is my understanding correct?
If you are using a factory and the calling code cares whether the returned animal can fly or walk, then the factory needs to return a more-derived type.
interface IAnimal { void Eat(); }
interface IFlyingAnimal : IAnimal { void Fly(); }
interface IWalkingAnimal : IAnimal { void Walk(); }
class Tiger : IWalkingAnimal
{
public void Eat() { }
public void Walk() { }
}
class Bird : IFlyingAnimal
{
public void Eat() { }
public void Fly() { }
}
// The factory lets the caller choose which type of animal it wants:
class AnimalFactory
{
public IFlyingAnimal GetFlyingAnimal() { return new Bird(); }
public IWalkingAnimal GetWalkingAnimal() { return new Tiger(); }
}
// or, you can use separate factories:
class FlyingAnimalFactory
{
public IFlyingAnimal Get() { return new Bird(); }
}
class WalkingAnimalFactory
{
public IWalkingAnimal Get() { return new Tiger(); }
}
This may or may not be the right solution, depending on the code you are writing. You should choose a pattern that fits your needs.
Your original factory accepts an int type parameter, which makes me think the calling code probably knows it needs a Tiger or a Bird. So other solutions might be to not use a factory, or have the factory return a Tiger specifically:
public void AnimalFactory
{
public Tiger GetTiger() { return new Tiger(); }
public Bird GetBird() { return new Bird(); }
}
In C#, I have a parent class with a public member. I want to derive the parent class, then derive the class of the public member, so as to create and access new methods, as follows...
public class Animal { }
public class Sheep : Animal {
public void makeALamb() { }
}
public class Farm
{
public Animal myAnimal;
}
public class SheepFarm : Farm {
public void SheepFarm() {
this.myAnimal = new Sheep();
this.myAnimal.makeALamb();
}
}
This code doesn't compile. "Animal does not contain a definition for makeALamb()". But what I want to do is the essence of polymorphism, no? What am I missing? I'm greatly looking forward to finding out.
Thanks in advance!
Because myAnimal is of type Animal. As such, it can only access members of Animal... and Animal doesn't have a method makeALamb.
The right hand side of the assignment here:
this.myAnimal = new Sheep();
..says what it is. The left hand side says what your code sees it as. The left hand side in your assignment is:
public Animal myAnimal;
// ^^^^^^
Now.. pretend that what you've tried is possible.. consider this:
this.myAnimal = new Snake();
this.myAnimal.makeALamb(); // what does it call here?
this.myAnimal = new Giraffe();
this.myAnimal.makeALamb(); // what here?
..what should happen when you call makeALamb on a Snake instance? ...
If I'm guessing correctly what you're intending to do, consider using generics:
public class Farm<TAnimal> where TAnimal : Animal
{
public TAnimal myAnimal;
}
public class SheepFarm : Farm<Sheep>
{
public void SheepFarm()
{
this.myAnimal = new Sheep();
this.myAnimal.makeALamb();
}
}
makeALamb() is a method of Sheep, not Animal. Sheep derives from Animal, not the other way around.
this.myAnimal is defined as an Animal. Animal does not have a makeALamb method. Since you put a Sheep in this.myAnimal, you could cast it:
((Sheep)this.myAnimal).makeALamb();
This effectively says: "Take this.myAnimal, treat is as a Sheep and call makeALamb() on it". If this.myAnimal is not really a Sheep at run-time, you'll get an exception.
The idea is that your Animal can be instantiated as Sheep, but it will handle only the members defined on Animal. It is as simple as: Sheep is an Animal, but Animal is not a Sheep, so the Animal can not makeALamb() :)
You have to cast your Animal instance to Sheep if you want to access makeALamb method.
public void SheepFarm()
{
this.myAnimal = new Sheep();
((Sheep)this.myAnimal).makeALamb();
}
Without a cast myAnimal is considered as type of Animal and therefore you can only access the members of Animal and the members of base class(es) of Animal (which there is no base class olf Animal in this case).
On the other hand, ofcourse this is not an elegant and secure way to access a class member.If you want to access some common members via a base class instance, then you should declare that members in your base class (maybe as abstract or virtual), and then implement (or override) them in derived classes.
you have not defined the Farm class well. Here is example:
public class Animal { }
public class Sheep : Animal {
public void makeALamb() { }
}
public class Goat: Animal {
public void makeAGoat() { }
}
public class Farm
{
public Goat myGoat;
public Sheep mySheep;
}
public class MyFarm : Farm {
public void MyFarm() {
this.mySheep= new Animal();
this.mySheep.makeALamb();
}
}
Every animal is not goat but every goat is an animal.
Since, you want to use polymorphism, change your code to:
public abstract class Animal
{
public abstract void makeChild();
}
public class Sheep : Animal
{
public override void makeChild()
{
Console.WriteLine("A lamb is born.");
}
}
public class Cow : Animal
{
public override void makeChild()
{
Console.WriteLine("A calf is born.");
}
}
public class Farm
{
public Animal myAnimal;
}
public class SheepFarm : Farm
{
public SheepFarm()
{
this.myAnimal = new Sheep();
this.myAnimal.makeChild();
}
}
public class CowFarm : Farm
{
public CowFarm()
{
this.myAnimal = new Cow();
this.myAnimal.makeChild();
}
}
and, use the following "Main()" method:
class Program
{
static void Main(string[] args)
{
Farm sf = new SheepFarm();
Farm cf = new CowFarm();
}
}
However, I should point to you that this is not a good use case scenario. A better and simpler use case of polymorphism would be to get rid of the Farm classes and use the following "Main()" method instead of the previous one:
class Program
{
static void Main(string[] args)
{
Animal[] animals = {
new Sheep(),
new Cow(),
new Sheep(),
new Cow(),
new Cow()
};
foreach (Animal animal in animals)
{
animal.makeChild();
}
}
}
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 ""; } }
}
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();
}