c# - 检查属性是否等于常量的表达式

标签 c# lambda expression

我正在尝试组合两个工作表达式。

  • left:返回属性值的表达式

    Expression<Func<TimeSlot, Guid>> left = x => x.TimeSlotId;
    
  • 右:返回常量值(变量guid的值)的表达式

    Expression<Func<TimeSlot, Guid>> right = Expression.Lambda<Func<TimeSlot, Guid>>
                        (Expression.Constant(guid, typeof(Guid)), input);
    

现在我想将这两个表达式打包到另一个使两个结果相等的表达式中。这有效:

    // given a TimeSlot slot which guid is equal to the constent
    bool eq1 = left.Compile()(slot) == right.Compile()(slot); // true

但这行不通 ParameterExpression 输入 = Expression.Parameter(typeof(TimeSlot));

        Expression<Func<TimeSlot, bool>> expression = Expression.Lambda<Func<TimeSlot, bool>>
            (Expression.Equal(left, right), input);

        bool eq2 = expression.Compile()(slot); // false

我完全困惑为什么这个结果会不同。特别是因为这个表达式的 DebugView 看起来像这样:

{Param_0 => (x => x.TimeSlotId == Param_0 => 351155b2-20a5-4c48-8722-ddf0e1f9055a)}

=

.Lambda #Lambda1<System.Func`2[SilverFit.Database.Model.TimeSlot,System.Boolean]>(SilverFit.Database.Model.TimeSlot $var1)
{
    .Lambda #Lambda2<System.Func`2[SilverFit.Database.Model.TimeSlot,System.Guid]> == .Lambda #Lambda3<System.Func`2[SilverFit.Database.Model.TimeSlot,System.Guid]>
}

.Lambda #Lambda2<System.Func`2[SilverFit.Database.Model.TimeSlot,System.Guid]>(SilverFit.Database.Model.TimeSlot $x) {
    $x.TimeSlotId
}

.Lambda #Lambda3<System.Func`2[SilverFit.Database.Model.TimeSlot,System.Guid]>(SilverFit.Database.Model.TimeSlot $var1) {
    .Constant<System.Guid>(351155b2-20a5-4c48-8722-ddf0e1f9055a)
}

有人知道创建比较表达式和常量结果的表达式的正确方法吗?

最佳答案

您看到的调试输出准确地告诉您发生了什么以及为什么它不起作用。特别是,您与等式表达式比较的不是表达式返回的值,而是表达式本身。

一个重要线索是两个表达式都需要输入,但即使在调试输出中,您也可以看到该输入仅在相等比较的一侧使用,并且仅作为第二个表达式的输入参数。

实际上,单独编译两个表达式是一个不错的解决方案。您甚至可以缓存编译结果:

Func<TimeSlot, Guid> d1 = left.Compile(), d2 = right.Compile();
Func<TimeSlot, bool> d2 = x => d1(x) == d2(x);

但是如果您确实想将操作组成单个表达式,那么您可以这样做:

ParameterExpression param1 = Expression.Parameter(typeof(TimeSlot));
Expression<Func<TimeSlot, bool>> expression = Expression.Lambda<Func<TimeSlot, bool>>(
    Expression.Equal(
        Expression.Invoke(left, param1),
        Expression.Invoke(right, param1)),
    param1);

这是演示该技术的完整代码示例:

class Program
{
    class A
    {
        public Guid Guid { get; private set; }

        public A()
        {
            Guid = Guid.NewGuid();
        }
    }

    static void Main(string[] args)
    {
        // Set up data values
        A a = new A();
        Guid guid = a.Guid;

        // Create expressions to be composed
        Expression<Func<A, Guid>> e1 = arg => arg.Guid, e2 = arg => guid;

        // Create lambda expression: invoke both expressions, compare the result
        ParameterExpression param1 = Expression.Parameter(typeof(A));
        Expression<Func<A, bool>> e3 = Expression.Lambda<Func<A, bool>>(
            Expression.Equal(
                Expression.Invoke(e1, param1),
                Expression.Invoke(e2, param1)),
            param1);

        // Compile to an actual delegate instance
        Func<A, bool> d1 = e3.Compile();

        // Check the result
        Console.WriteLine(d1(a));
    }
}

关于c# - 检查属性是否等于常量的表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27530340/

相关文章:

c# - 这是清除 C# MemoryCache 的好解决方案吗?

c# - 反射 - 作为接口(interface)的类的 GetProperties

c++ - QtConcurrency::mapped 成员函数

c++ - 将 lambda 传递给函数模板

java - 在使用流 API 的 Java 8 中,如何从需要多次计算的 Map 返回实例

.net - WhereNot linq 表达式

c# - 来自 C# 的 IronPython 生成器的优雅迭代

c# - 将数据从 C# 传递到 Electron

scala - 类型模式匹配为什么变量是必须的

javascript - 如何替换字符串中的标记?