无法使用Expression比较NAN

时间:2014-02-04 06:35:37

标签: wpf linq lambda expression

我正在使用Expression来比较值,我正在使用以下代码,

创建lambda表达式的方法。

    public static class Test
{
    public static Expression<Func<T, bool>> TransformToPredicate<T>(Expression<Func<T, double>> getvalue, double value)
    {
        System.Linq.Expressions.Expression equals = System.Linq.Expressions.Expression.Equal(getvalue.Body,
                                             System.Linq.Expressions.Expression.Constant(value));
        return System.Linq.Expressions.Expression.Lambda<Func<T, bool>>(equals, getvalue.Parameters);
    }
}

在下面的代码中,在比较Nan和Nan值时,它返回false。使用Expressioons时如何克服这个问题?我需要以更通用的方式做到这一点吗?

           Employee emp = new Employee();
        emp.SickLeaveHours = double.NaN;
        Expression<Func<Employee, double>> getfunc = x => x.SickLeaveHours;
        var predicate = Test.TransformToPredicate<Employee>(getfunc, double.NaN);
        var func = predicate.Compile();
        var flag = func(emp);

当我使用除Nan值以外的代码时,下面的代码工作正常。

            Employee emp = new Employee();
        emp.SickLeaveHours = 10.0;
        Expression<Func<Employee, double>> getfunc = x => x.SickLeaveHours;
        var predicate = Test.TransformToPredicate<Employee>(getfunc, 10.0);
        var func = predicate.Compile();
        var flag = func(emp);

我知道double.Nan == double.Nan将返回false,我们必须使用double.IsNAN或value!= value。但是我不确定在使用表达式时如何做到这一点。

1 个答案:

答案 0 :(得分:3)

您正在通过对象引用进行比较。这就是为什么你总是得到假的回报。但是每种类型都提供Equals()方法。为了比较两个双重或两个相同类型,您应该调用它们的Equals函数。调用equals函数与 Expression.Equal 不相同。

这是一个演示:

var wrong =
    System.Linq.Expressions.Expression.Lambda<Func<bool>>(
    System.Linq.Expressions.Expression.Equal(System.Linq.Expressions.Expression.Constant(double.NaN),
    System.Linq.Expressions.Expression.Constant(double.NaN))).Compile();

// is always false
bool result = wrong();

ConstantExpression first = System.Linq.Expressions.Expression.Constant(double.NaN, typeof(double));
ConstantExpression second = System.Linq.Expressions.Expression.Constant(double.NaN, typeof(double));

var right =
    System.Linq.Expressions.Expression.Lambda<Func<bool>>(
    System.Linq.Expressions.Expression.Call(first, first.Type.GetMethod("Equals", new[] { second.Type }), second)).Compile();

// will always be true
result = right();