Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# generics with interfaces

Tags:

c#

generics

I am trying to learn how to create generic classes with c#. Can someone explain why I get a compile error when I run this program.

I have created the IZooAnimal interface. All zoo animals will implement this interface.

public interface IZooAnimal
{
    string Id { get; set; }
}

public class Lion : IZooAnimal
{
    string Id { get; set; }
}

public class Zebra : IZooAnimal
{
    public string Id { get; set; }
}

The ZooCage will hold animals of the same Type

public class ZooCage<T> where T : IZooAnimal
{
    public IList<T> Animals { get; set; }
}

The zoo class have cages

public class Zoo
{
    public IList<ZooCage<IZooAnimal>> ZooCages { get; set; }
}

The program that uses the classes

class Program
{
    static void Main(string[] args)
    {
        var lion = new Lion();
        var lionCage = new ZooCage<Lion>();
        lionCage.Animals = new List<Lion>();
        lionCage.Animals.Add(lion);

        var zebra = new Zebra();
        var zebraCage = new ZooCage<Zebra>();
        zebraCage.Animals = new List<Zebra>();
        zebraCage.Animals.Add(zebra);

        var zoo = new Zoo();
        zoo.ZooCages = new List<ZooCage<IZooAnimal>>();

       zoo.ZooCages.Add(lionCage);
    }
}

When I compile I get the following error: Error 2 Argument 1: cannot convert from 'ConsoleApplication2.ZooCage<ConsoleApplication2.Lion>' to 'ConsoleApplication2.ZooCage<ConsoleApplication2.IZooAnimal>'

What changes do I have to do in order to make my program run?

like image 429
user2714000 Avatar asked Aug 24 '13 17:08

user2714000


1 Answers

@DanielMann's answer is quite good, but suffers from one drawback: the original IList interface cannot be used with the ICage interface. Instead, the ICage has to expose a ReadOnlyCollection, and expose a new method called CageAnimal.

I've also re-written the code using a similar approach. My ICage implementation is much weaker, but it allows you to stick with IList semantics inside.

public interface IZooAnimal
{
    string Id { get; set; }
}

public class Lion : IZooAnimal
{
    public string Id { get; set; }
}

public class Zebra : IZooAnimal
{
    public string Id { get; set; }
}

public interface ICage
{
    IEnumerable<IZooAnimal> WeaklyTypedAnimals { get; }
}

public class Cage<T> : ICage where T : IZooAnimal
{
    public IList<T> Animals { get; set; }

    public IEnumerable<IZooAnimal> WeaklyTypedAnimals
    {
        get { return (IEnumerable<IZooAnimal>) Animals; }
    }
}

public class Zoo
{
    public IList<ICage> ZooCages { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        var lion = new Lion();
        var lionCage = new Cage<Lion>();
        lionCage.Animals = new List<Lion>();
        lionCage.Animals.Add(lion);

        var zebra = new Zebra();
        var zebraCage = new Cage<Zebra>();
        zebraCage.Animals = new List<Zebra>();
        zebraCage.Animals.Add(zebra);

        var zoo = new Zoo();
        zoo.ZooCages = new List<ICage>();

        zoo.ZooCages.Add(lionCage);
    }
}
like image 121
CSJ Avatar answered Oct 20 '22 16:10

CSJ