最有效的方法来测试拉姆达前pressions平等 [英] Most efficient way to test equality of lambda expressions

查看:120
本文介绍了最有效的方法来测试拉姆达前pressions平等的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给定一个方法签名:

 公共BOOL AreTheSame< T>(防爆pression< Func键< T,对象>> EXP1,防爆pression< Func键< T,对象>> EXP2 )

什么是最有效的方式说,如果两位前pressions是一样的吗?这只需要简单的前pressions工作,我的意思是所有的将是支持将是简单MemberEx pressions,如c => c.ID。

一个例子电话可能是:

  AreTheSame<使用者>(U1 => u1.ID,U2 => u2.ID); - >将返回true。


解决方案

嗯...我想你不得不解析树,检查每个的节点类型和成员。我敲了一个例子...

 使用系统;
使用System.Linq.Ex pressions;
Test类{
    公共字符串美孚{搞定;组; }
    公共字符串酒吧{搞定;组; }
    静态无效的主要()
    {
        布尔TEST1 = FuncTest&所述;试验> .FuncEqual(X => x.Bar,Y => y.Bar),
            TEST2 = FuncTest&所述;试验> .FuncEqual(X => x.Foo,Y => y.Bar);
    }}
//这个只存在,使其更容易调用,即让我可以使用FuncTest< T>同
//通用型推理;如果使用双重泛型方法,你需要指定
//两个参数,这是一种痛苦...
静态类FuncTest< TSource>
{
    公共静态布尔FuncEqual< TValue>(
        防爆pression<&Func键LT; TSource,TValue>> X,
        防爆pression<&Func键LT; TSource,TValue>> Y)
    {
        返回FuncTest.FuncEqual&下; TSource,TValue>(X,Y);
    }
}
静态类FuncTest {
    公共静态布尔FuncEqual< TSource,TValue>(
        防爆pression<&Func键LT; TSource,TValue>> X,
        防爆pression<&Func键LT; TSource,TValue>> Y)
    {
        返回例pressionEqual(X,Y);
    }
    私人静态布尔防爆pressionEqual(前pression X,防爆pression Y)
    {
        //处理简单的情况下,第一...
        如果(的ReferenceEquals(X,Y))返回true;
        如果(X == NULL ||ÿ== NULL)返回false;
        如果(x.NodeType!= y.NodeType
            || !x.Type = y.Type)返回false;        开关(x.NodeType)
        {
            案例防爆pressionType.Lambda:
                返回前pressionEqual(((LambdaEx pression)X)。体,((LambdaEx pression)Y)。体);
            案例防爆pressionType.MemberAccess:
                MemberEx pression MEX =(MemberEx pression)X,MEY =(MemberEx pression)Y;
                返回mex.Member == mey.Member; //应该真正考验下游EX pression
            默认:
                抛出新NotImplementedException(x.NodeType.ToString());
        }
    }
}

Given a method signature:

public bool AreTheSame<T>(Expression<Func<T, object>> exp1, Expression<Func<T, object>> exp2)

What would be the most efficient way to say if the two expressions are the same? This only needs to work for simple expressions, by this I mean all that would be "supported" would be simple MemberExpressions, eg c => c.ID.

An example call might be:

AreTheSame<User>(u1 => u1.ID, u2 => u2.ID); --> would return true

解决方案

Hmmm... I guess you'd have to parse the tree, checking the node-type and member of each. I'll knock up an example...

using System;
using System.Linq.Expressions;
class Test {
    public string Foo { get; set; }
    public string Bar { get; set; }
    static void Main()
    {
        bool test1 = FuncTest<Test>.FuncEqual(x => x.Bar, y => y.Bar),
            test2 = FuncTest<Test>.FuncEqual(x => x.Foo, y => y.Bar);
    }

}
// this only exists to make it easier to call, i.e. so that I can use FuncTest<T> with
// generic-type-inference; if you use the doubly-generic method, you need to specify
// both arguments, which is a pain...
static class FuncTest<TSource>
{
    public static bool FuncEqual<TValue>(
        Expression<Func<TSource, TValue>> x,
        Expression<Func<TSource, TValue>> y)
    {
        return FuncTest.FuncEqual<TSource, TValue>(x, y);
    }
}
static class FuncTest {
    public static bool FuncEqual<TSource, TValue>(
        Expression<Func<TSource,TValue>> x,
        Expression<Func<TSource,TValue>> y)
    {
        return ExpressionEqual(x, y);
    }
    private static bool ExpressionEqual(Expression x, Expression y)
    {
        // deal with the simple cases first...
        if (ReferenceEquals(x, y)) return true;
        if (x == null || y == null) return false;
        if (   x.NodeType != y.NodeType
            || x.Type != y.Type ) return false;

        switch (x.NodeType)
        {
            case ExpressionType.Lambda:
                return ExpressionEqual(((LambdaExpression)x).Body, ((LambdaExpression)y).Body);
            case ExpressionType.MemberAccess:
                MemberExpression mex = (MemberExpression)x, mey = (MemberExpression)y;
                return mex.Member == mey.Member; // should really test down-stream expression
            default:
                throw new NotImplementedException(x.NodeType.ToString());
        }
    }
}

这篇关于最有效的方法来测试拉姆达前pressions平等的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆