LINQ - 使用 Predicate<T> 调用 Filter

3

我希望在我的其中一个课程中提供一种过滤某些元素的方法。为了保持我的界面尽可能干净和自我解释,我想让我的过滤器属性是一个Predicate<T>

这是我的类的一个简化示例:

public class ObjectAdapter
{
    public ObjectAdapter()
    {
        MemberFilter = DefaultFilter;
    }

    public Predicate<PropertyInfo> MemberFilter { get; set; }

    public virtual bool DefaultFilter(PropertyInfo info)
    {
        if (info.Name != "Test")
            return true;
        else
            return false;
    }
}

我的想法是让用户可以轻松地设置MemberFilter,因此没有必要创建一个继承自我的类并覆盖DefaultFilter函数的类。

问题:

在我的ObjectAdapter中,如果我尝试执行

something.GetType().GetProperties().Filter(MemberFilter)

我遇到了一个奇怪的编译错误:

Error: cannot convert from 'System.Predicate<System.Reflection.PropertyInfo>' to 'System.Func<System.Reflection.PropertyInfo,bool>'

对我来说这没有任何意义,因为MemberFilter基本上是一个delegate bool Predicate<PropertyInfo>(PropertyInfo obj),它应该与Func<PropertyInfo, bool>相同,对吧?

2个回答

2
问题在于,虽然对于相同类型 TPredicate<T>Func<T,bool> 具有相同的参数和返回值类型,但它们仍然是不同的(因此不兼容的)委托类型。使用 Func<T,bool> 而不是 Predicate<T> 可以解决问题,因为它们之间没有直接转换的方法。

1
好的,但编译器如何将 public virtual bool Filter(PropertyInfo) 转换为 Func<PropertyInfo, bool> 呢?如果我在那里放置 DefaultFilter 而不是 MemberFilter,它也可以正常工作。对我来说更奇怪的是,它成功地将 Filter(PropertyInfo) 转换为 Predicate<PropertyInfo>,但然后无法将 Predicate<PropertyInfo> 转换为 Func<PropertyInfo, bool> - Florian Segginger
2
@FlorianSegginger 这是因为方法组确实有转换。在底层,你会看到它明确地执行类似于 new Predicate<PropertyInfo>(DefaultFilter)new Func<PropertyInfo, bool>(DefaultFilter) 的操作。虽然委托类型之间没有转换,但方法组并不是委托(至少目前还不是) :) - Luaan
1
这是因为 public virtual bool Filter(PropertyInfo) 可以被分配给 Predicate<PropertyInfo>Func<PropertyInfo,bool>,因为所需的签名匹配;然而 Func<PropertyInfo,bool> 不能直接分配给 Predicate<PropertyInfo>。当我第一次遇到它时,我也觉得很困惑。 - Codor

2

您需要使用 Func<PropertyInfo, bool>Where,因为您无法将 Predicate<PropertyInfo> 自动转换为 Func<PropertyInfo, bool>

public class ObjectAdapter
{
    public ObjectAdapter()
    {
        MemberFilter = DefaultFilter;
    }

    public Func<PropertyInfo, bool> MemberFilter { get; set; }

    public virtual bool DefaultFilter(PropertyInfo info)
    {
        if (info.Name != "Test")
            return true;
        else
            return false;
    }
}

并且

var oa = new ObjectAdapter();
var props= something.GetType().GetProperties().Where(oa.MemberFilter);

另一种选择是创建一个将 Predicate<PropertyInfo> 转换为 Func<PropertyInfo, bool> 的方法:
public class ObjectAdapter
{
    public ObjectAdapter()
    {
        MemberFilter = DefaultFilter;
    }

    public Predicate<PropertyInfo> MemberFilter { get; set; }

    public virtual bool DefaultFilter(PropertyInfo info)
    {
        if (info.Name != "Test")
            return true;
        else
            return false;
    }
}

并且

var oa = new ObjectAdapter();
Func<PropertyInfo, bool> func = new Func<PropertyInfo,bool>(oa.MemberFilter);
var props = something.GetType().GetProperties().Where(func);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接