多态的 Lambda 类

Lambdas over polymorphic classes

在下面的代码中,请注意 Bar 派生自 Foo。

class Program
{
    public class Foo
    {
        public string data { get; set; }
    }

    public class Bar : Foo
    {
    }

    static void Main(string[] args)
    {
        var bars = new List<Bar>();

        bars.Add(new Bar() { data = "hello" });
        bars.Add(new Bar() { data = "world" });

        var resultsA = GetFoos(bars, (b => b.data.StartsWith("h")));
        var resultsB = GetBars(bars, (b => b.data.StartsWith("h")));
    }

    static List<Foo> GetFoos(List<Foo> fooList, Func<Foo, bool> criteria)
    {
        return fooList.Where(criteria).ToList();
    }

    static List<Bar> GetBars(List<Bar> barList, Func<Bar, bool> criteria)
    {
        return barList.Where(criteria).ToList();
    }
}

GetFoos 方法调用导致此编译器错误消息: 参数 1:无法从“System.Collections.Generic.List<Program.Bar>”转换为“System.Collections.Generic.List<Program.Foo>

但是,当该行被注释掉时,对 GetBars() 的调用会正确执行。

我在这里想要完成的是针对共同祖先的查询 class,可以使用 linq 吗?

List 更新为 IEnumerable:

static IEnumerable<Foo> GetFoos(IEnumerable<Foo> fooList, Func<Foo, bool> criteria)
{
    return fooList.Where(criteria).ToList();
}

static IEnumerable<Bar> GetBars(IEnumerable<Bar> barList, Func<Bar, bool> criteria)
{
    return barList.Where(criteria).ToList();
}

这是因为 IEnumerable<Bar>IEnumerable<Foo> 的子类型。保留子类型是因为 IEnumerable<T>T.

上是协变的

IList<Boo>IList<Foo> 都不是另一个的子类型,因为 IList<T>T 上是不变的。

只能是接口covariant。由于您试图将 List<Derived> 分配给 List<Base>,因此您需要改用协变接口。 IEnumerable 已经是协变的,所以只需将代码更改为:

static List<Foo> GetFoos(IEnumerable<Foo> fooList, Func<Foo, bool> criteria)
{
    return fooList.Where(criteria).ToList();
}

static List<Bar> GetBars(IEnumerable<Bar> barList, Func<Bar, bool> criteria)
{
    return barList.Where(criteria).ToList();
}

证明IdeOne