将返回类型的基类型列表作为参数传递方法会导致错误的方法签名错误

时间:2014-03-06 08:50:45

标签: c# generics covariance

我正在尝试创建泛型方法来过滤几个方法的结果,这些方法返回从相同基类型派生的类型列表。我准备了我的问题的简化版本:

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>();
    }
}

方法

GetFilteredAnimals("Pe", GetCats)

无效,因为GetCats未返回Animal列表。是否可以为列表执行此类通用方法?据我所知,如果我使用单个对象而不是列表,它将起作用。

此工作代码为here on .NET Fiddle

1 个答案:

答案 0 :(得分:2)

假设您正在使用C#4+和.NET 4+,您可以使用generic covariance来实现此功能:

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

List<Cat>不能被视为List<Animal> - 但可以被视为IEnumerable<Animal>,因为IEnumerable<T>是协变的T

同样Func<T>T中是协变的,因此Func<List<Cat>>可以被视为Func<IEnumerable<Animal>> ...因此它会编译。