Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return list of interface type

I have three clasess that inherit from the same interface:

Apple:Resource
Banana:Resource
Orange:Resource

I another class I have lists with the type op each one:

private List<Apple> apples = new List<Banana>();
private List<Banana> bananas = new List<Empleado>();
private List<Orange> oranges = new List<Orange>();

Now I want a method that can return any of those lists, lets say something like this:

public List<Resource> getListOf(string resource)
{
    switch (resource)
    {
        case "apple": 
            return apples;
            break;
        case "bananas":
        return bananas;
            break;
        case "oranges":
        return oranges;
            break;
        default:
            Console.WriteLine("wrong fruit");
            break;
    }
}

This gives me the following error:

Cannot implicitly convert type 'System.Collections.Generic.List<Fruits.Apple>' to 'System.Collections.Generic.List<Fruits.Resource>'

I thought it would work the same manner as I can do:

foreach (Resource r in Fruitlist) {
    r.Meth();
}
like image 869
Trufa Avatar asked Mar 23 '23 13:03

Trufa


1 Answers

The feature that makes the code break by its absence is called generic type covariance. C# does support variance in generics, but only in interfaces (not concrete classes).

The foreach snippet works because it treats Fruitlist as an IEnumerable<Fruit>, and since that's a generic interface with an out (covariant) type parameter the compiler can view it as an IEnumerable<Resource>.

If it's acceptable for getListOf to return an IEnumerable<Resource> then changing the function signature will make the code compile. Otherwise the compiler would not be able to guarantee type safety, because you could write this code:

List<Resource> apples = this.getListOf("apple");
apples.Add(new Orange()); // adding a Resource to a List<Resource>, right?

Another option would be to return a non-generic type, in which case type safety would be again lost and the compiler would introduce runtime checks to make sure that you don't mix apples with oranges (but at least the code would work if it's well-behaved).

like image 87
Jon Avatar answered Mar 31 '23 15:03

Jon