多态的 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
在下面的代码中,请注意 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