C# 如何检查c谓词参数内的值?-判定谓词相等

C# 如何检查c谓词参数内的值?-判定谓词相等,c#,.net,.net-4.0,c#-3.0,c#-4.0,C#,.net,.net 4.0,C# 3.0,C# 4.0,我试图确定两个谓词的相等性: public T FirstOrDefault(Func<T, bool> predicate) { if (EntityCache.ContainsKey(predicate.GetHashCode())) return EntityCache[predicate.GetHashCode()]; else { var entity = _objectSet.FirstOrDefault<T&

我试图确定两个谓词的相等性:

public T FirstOrDefault(Func<T, bool> predicate)
{
    if (EntityCache.ContainsKey(predicate.GetHashCode()))
        return EntityCache[predicate.GetHashCode()];
    else
    {
        var entity = _objectSet.FirstOrDefault<T>(predicate);
        EntityCache.Add(predicate.GetHashCode(), entity);
        return entity;
    }
}
我遇到的问题是谓词的哈希代码没有考虑到其中使用的值,我不知道如何检索它们


例如,如果传递给上述方法的谓词是:r=>r.Id==Id,我如何在FirstOrDefault方法中查找'Id'的值?

您需要使用表达式的。它们包含func,但也包含语法树,您可以在运行时检查它们的“源代码”。

如果我理解正确,您正在尝试确定委托中捕获的变量的值。我很确定没有简单的方法可以做到这一点。。。如果使用表达式树而不是委托,可能会更简单? 另一个可能简单得多的选项是在EntityCache中将传递给代理的值与它们一起保存

还要注意的是

if (EntityCache.ContainsKey(predicate.GetHashCode()))
    return EntityCache[predicate.GetHashCode()];

最好使用TryGetValue

为什么要这样做?在接受Func时,语法的全部要点是,您不知道它是如何实现的。作为FirstOrDefault的实现者,您不需要知道方法的用户如何选择过滤结果。他们可能会选择使用Id属性,或者他们可能有一些完全不同的谓词。值得一提的是,您可以将其转换为Func,并假设它们返回pk,然后您可以调用谓词来获取T的当前实例的值。我猜答案是没有简单的方法可以做到这一点,因为我想保持传递任何谓词的灵活性,并且能够以某种方式确定该谓词和值集是否与以前传递的相同。但是,我必须承认,这种方式仍然很糟糕,你也不应该缓存谓词。例如,创建自己的类来封装字段名和字段值。就像新的QueryFilterId,12。这将导致一个更好的设计。问题是,尽管我想保持能够将任何谓词传递给方法的灵活性,但我只想以某种方式确定该谓词及其参数值集之前是否已被传递。我的建议不会以任何方式限制您,您可以创建任意一组过滤器表达式导数。创建一个param类型的抽象过滤器基类,该基类只有一个方法bool DoesItMatchT elem。然后派生一个SimpleFilterExpression,该表达式将属性名和值作为构造函数参数。然后可以随意添加任何其他派生类。然后确保所有类都提供GetHashCode和Equals,这将非常简单,因为您有这些简单的实现类。主要问题是,如果您在两个不同的位置使用一个简单的x=>x.Id==12表达式,编译器将其编译为两个不同的函数。比较代码或表达式将非常困难。例如,y=>12==y.Id执行相同的操作,但它已经是不同的代码。这是一场噩梦。因此,对于简单的情况,请使用我的建议,并将过滤器逻辑封装在类中。感谢TryGetValue提示,我们将使用它。nonono,-1。永远不要因为两个对象的散列码是鸽子洞而假设它们相等principle@erikkallen你完全正确,我甚至没有注意到他在使用哈希代码——但这和我的答案有什么关系呢?我只是指出if-contains-return[]模式更好地用TryGetValue方法实现——甚至这也是对我答案本质的旁白。。。