【问题标题】:How to examine value inside c# predicate parameter? - Determining predicate equality如何检查 C# 谓词参数中的值? - 确定谓词相等
【发布时间】:2010-12-26 19:23:46
【问题描述】:

我正在尝试确定两个谓词的相等性:

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&lt;T, bool&gt; 的语法的全部意义在于您不知道它是如何实现的。作为FirstOrDefault实施者,您不知道您的方法的用户 如何选择过滤结果。他们可能选择使用Id 属性,或者他们可能有一些完全不同的谓词。对于它的价值,您可以将其转换为采用 Func&lt;T, int&gt; 并假设他们正在返回 pk,然后您可以调用谓词来获取 T 的当前实例的值。
  • 我想答案是没有简单的方法可以做到这一点,因为我想保持传递任何谓词的灵活性,并且能够以某种方式确定谓词和值集是否相同作为之前通过的。

标签: c# .net .net-4.0 c#-3.0 c#-4.0


【解决方案1】:

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

【讨论】:

  • 但是,我不得不承认,这种做事方式仍然很臭,你也不应该缓存谓词。例如,创建您自己的封装字段名称和字段值的类。像新的 QueryFilter("Id", 12)。这将带来更好的设计。
  • 问题是虽然我想保持能够将任何我想要的谓词传递给该方法的灵活性,但我只是想以某种方式确定该谓词及其参数值集是否在之前传递过.
  • 我的建议不会以任何方式限制您,您可以创建任何一组过滤器表达式衍生物。创建一个参数类型为 的抽象过滤器基类,它有一个方法 bool DoesItMatch(T elem)。然后派生一个 SimpleFilterExpression,它将属性名称和值作为构造函数参数。然后随意添加任何其他派生类。然后确保所有类都提供 GetHashCode 和 Equals,这将非常简单,因为您有这些简单的实现类。
  • 主要问题是,如果您在 2 个不同的地方使用一个简单的 "x => x.Id == 12" 表达式,编译器会将其编译为 2 个不同的函数。比较代码或表达式将非常困难。例如 "y => 12 == y.Id" 的作用相同,但它已经是不同的代码。这是一场噩梦。因此,对于简单的情况,请使用我的建议并将过滤器逻辑封装在类中。
【解决方案2】:

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

还要注意,而不是

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

最好用TryGetValue

【讨论】:

  • 感谢 TryGetValue 提示,将使用它。
  • NONONONO,-1。永远不要假设两个对象是相等的,因为它们的哈希码是(鸽洞原则)
  • @erikkallen 你是绝对正确的(我什至没有注意到他正在使用哈希码)-但这与我的答案有什么关系?我只是指出if contains return [] 模式可以更好地使用TryGetValue 方法实现-即使那是我答案本质的一个旁白……
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多