Passing method with list of base type in return type as a parameter causes wrong method signature error

StackOverflow https://stackoverflow.com/questions/22219373

  •  10-06-2023
  •  | 
  •  

Question

I'm trying to create generic method to filter results from several method returning lists of types that are deriving from same base type. I prepared a simplified version of my problem:

using System;
using System.Collections.Generic;
using System.Linq;

public class Animal 
{
    public string Name { get; set; }
}
public class Cat : Animal { }
public class Dog : Animal { }


public class Program
{
    public static void Main()
    {
        Console.WriteLine(GetFilteredAnimals("Pe", GetCats));
    }

    private static List<Cat> GetCats()
    {   
        return new List<Cat>() { new Cat { Name = "Sphinx" }, new Cat { Name = "Persian" } };
    }

    private static List<Dog> GetDogs()
    {
        return new List<Dog>() { new Dog { Name = "Bulldog"}, new Dog { Name = "Dalmatian" } };
    }

    private static List<Animal> GetFilteredAnimals(string f, Func<List<Animal>> method)
    {
        var animals = method();

         return animals.Where(a => a.Name.StartsWith(f)).ToList<Animal>();
    }
}

The method

GetFilteredAnimals("Pe", GetCats)

does not work because GetCats does not return list of Animal. Is it possible to do such generic method for lists? As far as I know, if I used single objects instead of lists it would work.

The working code for this is here on .NET Fiddle

Was it helpful?

Solution

Assuming you're using C# 4+ and .NET 4+, you can get this to work using generic covariance:

private static List<Animal> GetFilteredAnimals(string f, Func<IEnumerable<Animal>> method)

A List<Cat> can't be treated as a List<Animal> - but it can be treated as an IEnumerable<Animal> because IEnumerable<T> is covariant in T.

Likewise Func<T> is covariant in T, so a Func<List<Cat>> can be treated as a Func<IEnumerable<Animal>>... so it then compiles.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top