Array co-variance in C# generic list - c#

I have an example where I want an abstract class interface to return something like this
abstract class AnimalProcessor {
public abstract IList<Animal> ProcessResults();
}
Then the concrete examples
class GiraffeProcessor : AnimalProcessor {
public override IList<Animal> ProcessResults() {
return new List<Giraffe>();
}
}
class LionProcessor : AnimalProcessor {
public override IList<Animal> ProcessResults() {
return new List<Lion>();
}
}
The problem is that the concrete classes need to have the same signature to override the ProcessResults() method so they need to return an IList<Animal>, however the ACTUAL data I want to return is an IList<Lion>, IList<Giraffe> etc, but then the calling code has to do
GiraffeProcessor processor = new GiraffeProcessor();
IList<Animal> results = processor.GetResults();
Which does not give me an Ilist which is what I want.
Problems
1) Above code does not compile. The giraffeProcessor has to return a concrete List<Animal>, you can populate it with Giraffe objects but the object type you construct to return has to be List<Animal>. Not ideal.
2) When you return the results, you can only get an IList<Animal>, not IList<Giraffe>. I have tried casting explicitly to IList<Giraffe> with
IList<Giraffe> results = (IList<Giraffe>) processor.GetResults();
which gives a runtime error, presumably because the object returned is NOT an IList<Giraffe>, it is an IList<Animal> which CONTAINS Giraffe objects.
Can anyone suggest what I am doing wrong here with my design as Im a bit stumped as to the best way to accomplish this.

How about:
abstract class AnimalProcessor<T> where T : Animal {
public abstract IList<T> ProcessResults();
}
class GiraffeProcessor : AnimalProcessor<Giraffe> {
public override IList<Giraffe> ProcessResults() {
return new List<Giraffe>();
}
}
class LionProcessor : AnimalProcessor<Lion> {
public override IList<Lion> ProcessResults() {
return new List<Lion>();
}
}

You could resolve this by declaring AnimalProcessor with a generic type constraint, e.g.
public abstract class AnimalProcessor<T> where T : Animal
{
public abstract IList<T> ProcessResults();
}
If that doesnt work, you could use the LINQ Cast operator, for example:
public class GiraffeProcessor : AnimalProcessor
{
public override IList<Animal> ProcessResults()
{
return new List<Giraffe>().Cast<Animal>();
}
}
Or, store the list internally as Animal but add Giraffe's to it, e.g.
public class GiraffeProcessor : AnimalProcessor
{
private List<Giraffe> _innerList = new List<Giraffe>();
public override IList<Animal> ProcessResults()
{
return new List<Animal>(innerList ); }
}
Best regards,

If you are using C# 4.0, you can ask yourself whether the processor should return IEnumerable<T> rather than IList<T>. If the answer is "yes", then you can profit from covariance:
abstract class AnimalProcessor {
public abstract IEnumerable<Animal> ProcessResults();
}
class GiraffeProcessor : AnimalProcessor {
public override IEnumerable<Animal> ProcessResults() {
return new List<Giraffe>();
}
}
class LionProcessor : AnimalProcessor {
public override IEnumerable<Animal> ProcessResults() {
return new List<Lion>();
}
}
You have a couple of advantages here. First, you could implement these as iterator blocks:
class GiraffeProcessor : AnimalProcessor {
public override IEnumerable<Animal> ProcessResults() {
yield break;
}
}
Second, and less trivially, you allow the client code to decide what kind of collection to dump the animals into -- if any. For example, consider that the consumer might want a LinkedList<Animal>:
var animals = new LinkedList<Animal>(animalProcessor.ProcessResults());
Or consider that the client might need only to iterate the sequence:
foreach (var animal in animalProcessor.ProcessResults())
{ /*... do something ...*/ }
In either case, if you were using a ToList() call in ProcessResults, you'd be creating a list for nothing. If the consumer really wants a List<Animal>, that can be accomplished very easily:
var animals = new List<Animal>(animalProcessor.ProcessResults());
Finally, you can also benefit from the generic approach, even if you change the interface type of the method's return value:
abstract class AnimalProcessor<T> where T : Animal {
public abstract IEnumerable<T> ProcessResults();
}
class GiraffeProcessor : AnimalProcessor<Giraffe> {
public override IEnumerable<Giraffe> ProcessResults() {
yield break;
}
}
class LionProcessor : AnimalProcessor<Lion> {
public override IEnumerable<Lion> ProcessResults() {
return Enumerable.Empty<Lion>();
}
}

Related

Casting variable of type Interface<TChild> to Interface<TParent>

When I try define an variable like that:
IVeterinarian<IAnimal> v = (IVeterinarian<IAnimal>)new CatVeterinarian();
These are an example for the interfaces and classes decleration:
interface IAnimal
{
}
class Dog : IAnimal
{
}
class Cat : IAnimal
{
}
interface IVeterinarian<TAnimal> where TAnimal : IAnimal
{
void Heal(TAnimal animal);
}
class DogVeterinarian : IVeterinarian<Dog>
{
public void Heal(Dog animal)
{
}
}
class CatVeterinarian : IVeterinarian<Cat>
{
public void Heal(Cat animal)
{
}
}
What's the difference btw my example and declaring IEnumerable of strings in a IEnumerable of objects variable?
Why am I getting an InvalidCastException.
Any ideas?
You can't create an instance like that;
IVeterinarian v = (IVeterinarian)new CatVeterinarian();
Because, you should pass a type which is implemented from IAnimal;
IVeterinarian<Cat> v = new CatVeterinarian();
EDIT
You are getting cast invalid exception because IVeterinarian<IAnimal> is not IVeterinarian<Cat> even implements it.
public interface IEnumerable<out T> : IEnumerable
{
IEnumerator<T> GetEnumerator();
}
As you see, IEnumerable uses out parameter and it makes it covariant. Please review this page.
In your case, you can't make your generic as covariant because the generic is being used as signature. By using covariants you can return derived types as you mentioned in the question.
IEnumerable<object> list = new List<string>();
In short, it has different purpose from your case which you want to try.
In my usecase, I wanted to take care differently each animal. I found an easy way to do it - Here's my solution:
Remove the generic from the IVeterinarian
Create a generic base Veterinarian class which implements IVeterinarian where T implements IAnimal
Create an abstract method in the base class with the same name that gets an animal argument in type T
Implement the original Heal method with calling the abstract method giving the animal argument after casting to T
In the Cat&Dog Veterinarian classes, just override the abstract method
Here's an example:
interface IAnimal
{
}
class Dog : IAnimal
{
}
class Cat : IAnimal
{
}
interface IVeterinarian
{
void Heal(IAnimal animal);
}
abstract class BaseVeterinarian<T> : IVeterinarian
where T : IAnimal
{
public void Heal(IAnimal animal)
{
Heal((T)animal);
}
protected abstract void Heal(T animal);
}
class DogVeterinarian : BaseVeterinarian<Dog>
{
protected override void Heal(Dog animal)
{
}
}
class CatVeterinarian : BaseVeterinarian<Cat>
{
protected override void Heal(Cat animal)
{
}
}
Be aware that you must send a correct IAnimal object as argument - or it will throw an InvalidCastException.
Now I can make IVeterinarian objects with different implementations almost like I whished in my question.
IVeterinarian v = new CatVeterinarian();
v.Heal(new Cat());
IVeterinarian v2 = new DogVeterinarian();
v2.Heal(new Dog());

Generic CloneInstance

I want create interface with CloneInstance method which return Generic class of that instance. For Example:
public interface ICloneableExtended<T> where T : this
{
T CloneInstance();
}
public class Car : ICloneableExtended
{
...
...
public Car CloneInstance()
{ .. }
}
Foo()
{
Car car ...;
var clonedCar = car.CloneInstance();
}
In definition of class Car, I need use only ICloneableExtended, not ICloneableExtended<T>. Is there some way how to do this?
You can accept a generic T parameter for the concrete class that will implement ICloneableExtended:
interface ICloneableExtended<T> {
Clone();
}
class Car : ICloneableExtended<Car> {
public Car Clone() {
throw new NotImplementedException();
}
}
You may consider to make T parameter covariant (if you wish to keep ICloneableExtended<Car> with many concrete classes - which will implement ICloneableExtended<T>):
interface ICloneableExtended<out T> {
Clone();
}
Note that you may not need a generic-less interface, you already have ICloneable (with all its drawbacks and misuses):
interface ICloneableExtended<out T> : ICloneable {
Clone();
}
For binary serializable types you may even implement a basic and reusable (but pretty inefficient) base class:
interface ICloneableExtended<T> : ICloneable {
T Clone();
}
abstract class Cloneable<T> : ICloneableExtended<T> {
public virtual T Clone() {
using (var ms = new MemoryStream()) {
var formatter = new BinaryFormatter();
formatter.Serialize(ms, this);
ms.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(ms);
}
}
object ICloneable.Clone() {
return Clone();
}
}
sealed class Car : Cloneable<Car> { }
With this approach each concrete class must implement ICloneableExtended<T> but you can't overload Clone() method differentiating only with return value then you'd better to implement ICloneableExtended<T> explicitly. A less confusing way (both for who implements this interface and who will use it) is to provide an extension method:
static class Extensions {
public static T Clone<T>(this object obj) {
var cloneable = obj as ICloneable;
if (cloneable != null)
return (T)cloneable.Clone();
using (var ms = new MemoryStream()) {
return (T)...
}
}
}
(here I'm using ICloneable for clarity but if you don't want to use it because of its worldwide random usage then just pick your own equivalent non-generic interface).

Casting generic parameter to subclass

Please look at the code bellow:
public class BaseClass
{
}
public class SubClass : BaseClass
{
}
public class QueryClass
{
public TBaseClass[] QueryBase<TBaseClass>() where TBaseClass : BaseClass
{
throw new NotImplementedException();
}
public TSubClass[] QuerySub<TSubClass>() where TSubClass : SubClass
{
throw new NotImplementedException();
}
public TClass[] Query<TClass>() where TClass : BaseClass
{
if (typeof(TClass).IsSubclassOf(typeof(SubClass)))
{
return QuerySub<TClass>(); // there is error The type 'TClass' must be convertible to SubClass
}
return QueryBase<TClass>();
}
}
The question is how to implement Query method. If it is possible..
What you are trying to do is doing something like this:
public class Animal { }
public class Dog : Animal { }
public void HandleAnimal<T>() where T : Animal
{
}
public void HandleDog<T>() where T : Dog
{
}
When you have a reference to Animal in this case, there is no way of knowing what typeof animal it is. Even if the method returns true, in the context of your code it is still always an Animal and you can't handle a dog when all you know is that the type is an animal. If you were handling instances of objects inside the method you could potentially start casting or instansiating the subclass if you know that it is a subclass and then pass that through.
Ended up with reflection.
if (typeof(TClass).IsSubclassOf(typeof(SubClass)))
{
var method = typeof(QueryClass).GetMethod("QuerySub").MakeGenericMethod(typeof (TClass));
return (TClass[]) method.Invoke(this, new object[0]);
}

Can I hold a List<> of Object Types of the same descendant?

I need to hold a list of object types that are allowed to do certain actions.
Example Animal has 3 descendants Tiger, Human, Hippo
I want to allow only Tigers and Hippos to be held in zoo cages? I need a list of animal types.
I would love something better than List<Type>
This is just a simplified example. I don't like animals in cages..
edit
Since it's not clear. I want to hold object types in the list and not actual objects.
Example:
List<Type> types = new List<Type>();
types.Add(typeof(Hippo));
types.Add(typeof(Tiger));
This has the limit that a programmer can do types.Add(typeof(Human)) and this is what I wan't to dissallow.
edit2
Just to clarify my question. I want to be able to dynamically Register allowed types and not having consequent ifs as some answers bellow.
If you want a list of only certain types:
There isn't anything in generics that can support what you are asking for, so simply create a custom type that allows you to store Type types and have code at runtime for guarding against invalid entries:
public class CagedTypes
{
private readonly List<Type> _types;
public void Add(Type t)
{
if (t == typeof(Hippo) || t == typeof(Tiger))
_types.Add(t);
}
}
Although I can't see why you might need this.
Alternative if you want a list of only certain types:
Do the same as above, but include the interface below and change the add check to something like:
public void Add(Type t)
{
if (t.GetInterfaces().Contains(typeof(ICanBeHeldInZooCage)))
_types.Add(t);
}
You could also use attributes, as you can query a type for any attributes using the GetAttributes method.
If you wish to only have certain instances in a list:
Create a marker interface:
public interface ICanBeHeldInZooCage
That Tiger and Hippo implement (doesn't have to do anything), then you can have:
var cagedAnimals = new List<ICanBeHeldInZooCage>();
Approach1 - via interfaces:
public interface ICageable
{ }
public abstract class Animal
{}
public class Hippo : Animal, ICageable
{}
public class Human : Animal, ICageable
{}
public IEnumerable<Type> GetCageableAnimals()
{
return GetAssemblyTypes(assembly:typeof(Animal).Assembly)
.Where(type=>IsDerivedFrom(type, typeof(Animal)))
.Where(type=>ImplementsInterface(type,typeof(ICageable)));
}
Approach 2 - via attribute:
public class InCageAttribute : Attribute
{ }
public abstract class Animal
{}
[InCage]
public class Hippo : Animal
{}
public class Human : Animal
{}
public IEnumerable<Type> GetCageableAnimals()
{
return GetAssemblyTypes(assembly:typeof(Animal).Assembly)
.Where(type=>IsDerivedFrom(type, typeof(Animal)))
.Where(type=>MarkedByAttribute(type,typeof(InCageAttribute)));
}
UPDATE
IMPORTANT
Both these approaches provide only runtime check. having compilation check implementation would be better, but don't know for know how to achieve that.
UPDATE2
For dynamic registration:
public class CageRegistry
{
private List<Type> _allowedTypes = new List<Type>();
public IEnumerable<Type> AllowedTypes{get{return _allowedTypes;}}
public bool TryAdd(Type type)
{
if(ImplementsInterface(type, typeof(ICageable)))// for approach with attributes code is pretty similar
{
_allowedTypes.Add(type);
return true;
}
return false;
}
}
PS2
Sorry for not implemented methods like MarkedByAttribute, IsDerivedFrom and ImplementsInterface - I just don't have visual studio on current machine yet and don't remember api exactly.
How about an Interface?
public interface ICageable {}
public abstract class Animal {}
public class Hippo : Animal, ICageable {}
public class Tiger : Animal, ICageable {}
public class Human : Animal, ICageable {}
public class Ape : Animal {}
....
List<ICageable> ZooAnimals = new List<ICageable>{hippo, tiger, human};
(writing from a Planet of the Apes perspective)
and if you need the types themselves in a list, well types are instances of the Type type, so whatever you create it will be a collection of types. You could encapsulate is like this:
public class CageableTypesCollection :
{
private List<Type> _cageableTypes;
public CageableTypesCollection()
{
_cageableTypes = new List<Type>();
}
public RegisterType(Type t)
{
if (!typeof(ICageable).IsAssignableFrom(t))
throw new ArgumentException("wrong type of type");
_cageableTypes.Add(t);
}
public UnregisterType(Type t)
{
....
}
.....
}
I would use an interface to determine if an animal is a ZooAnimal
public class Animal
{
public string Name;
}
public class Tiger : Animal, IZooAnimal
{
}
public class Human : Animal
{
}
public interface IZooAnimal
{
//Some zoo animal properties
}
And then check if the animal is a Zoo Animal if (a is IZooAnimal) below is a zoo class which you could use.
public class Zoo
{
public List<IZooAnimal> AnimalsInZoo = new List<IZooAnimal>();
public void AddAnimal(IZooAnimal a)
{
AnimalsInZoo.Add(a);
}
}
EDIT:
Ok now to do this with types and constrain the types to a ZooAnimal I have made a generic zoo class which takes T where T is a ZooAnimal - you could have a list of ZooAnimals or a list of tigers in our case.
public class Zoo<T> where T : IZooAnimal
{
public List<Type> AnimalTypes = new List<Type>();
public void AddType(Type a)
{
if (typeof(T) == a)
AnimalTypes.Add(a);
}
}
This will add type Tiger to the AnimalsInZoo. Hope this works for you.
Zoo<IZooAnimal> cage = new Zoo<IZooAnimal>();
cage.AddType(typeof(Tiger));
cage.AddType(typeof(Human));
Human is animal, Tiger is animal that should be in zoo. So in your case I'd create one more base class for Tiger and Hippo.
public class AnimalInZoo : Animal {}
public class Tiger : AnimalInZoo {}
public class Hippo : AnimalInZoo {}
public class Human : Animal {}
You can create helper function AddInZoo(AnimalInZoo obj) to add in you List<Type> m_Zoo:
void AddInZoo(AnimalInZoo obj)
{
m_Zoo.Add(obj.GetType());
}
The other option:
public abstract class Animal
{
public abstract bool IsCagable { get; }
}
And let the nested classes to implement their behavior.
Later then, the some sort of Zoo class which is mostly presented in the answers in this topic, inside the method Add must do the check:
public sealed class ZooList : List<Animal> // I believe you need Animal, not Type
{
// ... some implementations ...
public override sealed void Add(Animal animal)
{
if (!animal.IsCagable)
// Prevent from adding.
}
}

Elegant Dynamic Type Casting

I'd appreciate your advice on the following:
I'm using polymorphism. I have a base class and 30 sub classes that inherit this base class. I'm up casting instances of these sub classes to the base class type so that they can be handled in a more generic fashion.
My question is this.
I need to access a public property that is specific to a particular sub class. Do I need to write a giant case statement where I check the type and down cast accordingly in order to access the property I need or is there a more elegant solution?
static void Main(string[] args)
{
animal slyvester = new cat();
animal lassie = new dog();
animal silver = new horse();
// Big ugly type checking code. If I have 30 types to check is there a better way?
if (slyvester.GetType() == typeof(cat)) {
Console.WriteLine(((cat)(animal)slyvester).PurrStrength);
}
else if(slyvester.GetType() == typeof(dog)) {
}
else if (slyvester.GetType() == typeof(horse))
{
}
Console.ReadLine();
}
}
public class animal {
}
public class cat : animal {
private string _purrStrength = "Teeth Shattering";
public string PurrStrength {
get { return _purrStrength; }
set { _purrStrength = value; }
}
}
public class dog : animal {
}
public class horse : animal {
}
You should consider an interface based approach. With interfaces, you define a set of operations (a contract by which implementers must conform) which your types must define. E.g, we could define a base interface, IAnimal
public interface IAnimal
{
string GetSound();
}
From which we can define some animal types:
public class Cat : IAnimal
{
public string GetSound()
{
return "Meow!";
}
}
public class Dog : IAnimal
{
public string GetSound()
{
return "Woof!";
}
}
Now, when we want to declare our animal, we declare it of type IAnimal:
IAnimal cat = new Cat();
IAnimal dog = new Dog();
Console.WriteLine(cat.GetSound());
Console.WriteLine(dog.GetSound());
You could go one step further, and specialise your animals:
public class Cat : IAnimal
{
public virtual string GetSound()
{
return "Meow!";
}
}
public class BigCat : Cat
{
public override string GetSound()
{
return "Roar!";
}
}
In the latter example, I can make a default implementation of the cat's GetSound method, and then override it for my big cat.
Interface based programming hides away the need to horrible type conversions, because an interface guarantees a set of operations that will be provided.
If you don't have to know the exact type of the passed object, you just need a property value in case it doesn't exist in the base type, but it may or may not exists in the actual type, you can use reflection:
static void Main(string[] args)
{
animal slyvester = new cat();
animal lassie = new dog();
animal silver = new horse();
DoSomething(slyvester);
DoSomething(lassie);
DoSomething(silver);
Console.ReadLine();
}
static void DoSomething(animal entity)
{
string INeedThisProperty = "PurrStrength";
Type type = entity.GetType();
PropertyInfo property = type.GetProperty(INeedThisProperty);
if (property != null && property.CanRead)
{
Console.WriteLine("Found: {0}", property.GetValue(entity, null));
}
}
If in precise moment of property access you dont't have any clue what type is it, somehow you have to figure out it.
Or, what I personaly would do, is try to create virtual functions/properties on base class that describes my child classes action in more generic way, override them in child classes with concrete implementation and after call that functions/properties using upper casted objects.
The answer is to use polymorphism. The idea is to introduce a method in the base interface or as in this case the base class. Then just call this method! The runtime will automagically delegate the call to the correct type.
Look at the modified implementation below:
public abstract class Animal
{
public abstract void OutputInterestingFact();
}
public class Cat : Animal {
private string _purrStrength = "Teeth Shattering";
public string PurrStrength {
get { return _purrStrength; }
set { _purrStrength = value; }
}
public override void OutputInterestingFact()
{
Console.WriteLine(PurrStrength);
}
}
public class Dog : Animal {
public override void OutputInterestingFact()
{
// Do stuff for dog here
}
}
public class Horse : Animal {
public override void OutputInterestingFact()
{
// Do stuff for horse here
}
}
I made the Animal into an abstract class. You could also make the OutputInterestingFact method virtual with an empty method body.
I've also renamed your classes to begin with an upper case letter. Make this a habit since this is practice in C# and other programmers will find your code easier to read.
Now, to use this just call the method.
slyvester.OutputInterestingFact();
Is that elegant enough?
Your code does not cover all the cases that I can think of, but just 2 possible solutions:
class Animal {
public abstract string PropertyValue { get; set; }
}
class Cat : Animal {
public override string PropertyValue {
get { return PurrStrength; }
set { PurrStrength = value; }
}
}
or, for multiple properties:
class Animal {
public virtual string[] GetPropertyValues() { return null; }
}
class Cat : Animal {
public override string[] GetPropertyValues() {
return new string[] { PurrStrength };
}
}

Categories

Resources