【问题标题】:Why is it impossible to cast Func<T, bool> to Predicate<T>?为什么无法将 Func<T, bool> 强制转换为 Predicate<T>?
【发布时间】:2020-01-20 15:20:11
【问题描述】:

我发现自己不得不对列表中的元素做一些事情,然后将它们从该列表中删除:

foreach (var element in someList.Where(e => e.IsMatching))
{
    // do some stuff
}

someList.RemoveAll(e => e.IsMatching);

这很完美,但我不喜欢重复的 lambda,所以我声明了一个 Func&lt;T, bool&gt; x = e =&gt; e.IsMatching;,然后尝试使用 x 作为 .Where.RemoveAll 的参数,但我无法使用x for .RemoveAll 因为它的重载只接受Predicate&lt;T&gt;

为什么不能进行隐式或显式强制转换,因为两者具有相同的返回和参数类型?

(我不是在寻找进行转换的方法,关于它的一切都已经in this quesion

【问题讨论】:

  • 为什么不使用链接线程的解决方案?
  • ...因为该语言不允许不同委托类型之间的隐式或显式转换(即使它们具有兼容的签名)
  • @PavelAnikhouski 正如问题中提到的那样,我不是在寻找执行转换的方法,我只是在问为什么无法进行演员表
  • 因为不需要?请记住,Func 是一个相对较新的添加:据我所知,最初的意图是委托的每个 use 都会获得自己的委托类型:委托的名称和它的参数名称与参数的类型 一样重要。在那之下,你为什么能够隐式地将Predicate&lt;T&gt;(用于确定对象是否符合标准)转换为Converter&lt;T, bool&gt;(用于数据类型之间的映射):它们是完全不同的东西!然后 linq 出现了......
  • 如果你有两个类,比如class A { int a; }class B { int a; },你也不会想到这些类型之间的可分配性。

标签: c# delegates


【解决方案1】:

IEnumerable&lt;T&gt;.Where 扩展方法和List&lt;T&gt;RemoveAll 方法采用两种不同的类型有点傻。但是,这是一个简单的解决方法,因为本地函数可用于初始化 Func&lt;int, bool&gt;Predicate&lt;int&gt;

var l = new List<int> {1, 2, 3, 5, 5, 6, 6};
bool Pred(int i) => i < 5;
var wh = l.Where(Pred);
var rem = l.RemoveAll(Pred);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-04-05
    • 2010-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-14
    相关资源
    最近更新 更多