Linq和Equality Operator:类型'System.Int32'的表达式不能用于'System.Object'类型的参数

Cod*_*ike 10 .net c# linq operator-overloading

我正在尝试覆盖C#中的相等(==)运算符来处理将任何类型与自定义类型进行比较(自定义类型实际上是null周围的包装器/框).

所以我有这个:

internal sealed class Nothing
{
    public override bool Equals(object obj)
    {
        if (obj == null || obj is Nothing)
            return true;
        else
            return false;
    }

    public static bool operator ==(object x, Nothing y)
    {
        if ((x == null || x is Nothing) && (y == null || y is Nothing))
            return true;
        return false;
    }
   ...
}
Run Code Online (Sandbox Code Playgroud)

现在,如果我打电话:

Nothing n = new Nothing();
bool equal = (10 == n);
Run Code Online (Sandbox Code Playgroud)

它工作得很好.但是,如果我尝试通过Linq表达式树执行相同的操作:

exp = Expression.Equal(
    Expression.Constant(10), 
    Expression.Constant(new Nothing(), typeof(Nothing))
);
Run Code Online (Sandbox Code Playgroud)

它抛出了异常:

System.ArgumentException : Expression of type 'System.Int32' cannot be used for parameter of type 'System.Object' of method 'Boolean op_Equality(System.Object, PARTSFinder.Rules.Runtime.RulesNothing)'
    at System.Linq.Expressions.Expression.ValidateArgumentTypes(MethodInfo method, ReadOnlyCollection`1& arguments)
    at System.Linq.Expressions.Expression.ValidateCallArgs(Expression instance, MethodInfo method, ReadOnlyCollection`1& arguments)
    at System.Linq.Expressions.Expression.Call(Expression instance, MethodInfo method, IEnumerable`1 arguments)
    at System.Linq.Expressions.Expression.Call(Expression instance, MethodInfo method, Expression[] arguments)
    at System.Linq.Expressions.ExpressionCompiler.GenerateBinaryMethod(ILGenerator gen, BinaryExpression b, StackType ask)
Run Code Online (Sandbox Code Playgroud)

关于为什么基本系统可以将Int32转换为Object的任何想法,但Linq不能,或者我如何解决这个问题?

整个事情盯着看,因为Linq也无法首先将Int32与Object进行比较:

exp = Expression.Equal(
    Expression.Constant(10), 
    Expression.Constant(null)
);
Run Code Online (Sandbox Code Playgroud)

引发异常,指出"System.Int32"和"System.Object"没有比较运算符.


快速跟进:

以下工作没有问题:

exp = Expression.Equal(
    Expression.Constant(10, typeof(object)), 
    Expression.Constant(new Nothing(), typeof(Nothing))
);

exp = Expression.Equal(
    Expression.Constant(10, typeof(object)), 
    Expression.Constant(null)
);
Run Code Online (Sandbox Code Playgroud)

所以特意将一切都投射到物体上 那么Linq内部没有处理继承吗?多奇怪啊...


后续#2:

我也尝试过使用自定义比较方法:

exp = Expression.Equal(
    Expression.Constant(10),
    Expression.Constant(null),
    false,
    this.GetType().GetMethod("ValueEquals", BindingFlags.Public | BindingFlags.Static)
);

    public static bool ValueEquals(object x, object y)
    {
        if (x == null && y == null)
            return true;
        if (x.GetType() != y.GetType())
            return false;
        return x == y;
    }
Run Code Online (Sandbox Code Playgroud)

这也引发了一个例外:

System.InvalidOperationException : The operands for operator 'Equal' do not match the parameters of method 'ValueEquals'.
    at System.Linq.Expressions.Expression.GetMethodBasedBinaryOperator(ExpressionType binaryType, Expression left, Expression right, MethodInfo method, Boolean liftToNull)
Run Code Online (Sandbox Code Playgroud)

但是再次将所有内容直接投射到对象上:

exp = Expression.Equal(
    Expression.Constant(10, typeof(object)),
    Expression.Constant(null, typeof(object)),
    false,
    this.GetType().GetMethod("ValueEquals", BindingFlags.Public | BindingFlags.Static)
);
Run Code Online (Sandbox Code Playgroud)

所以我想我有我的解决方法......将所有内容都转换为对象并使用自定义比较方法.我仍然感到惊讶Linq没有像普通C#那样自动进行转换.

Mar*_*ell 9

null有什么问题?重新找失了intvs null,试试int?:

exp = Expression.Equal(
    Expression.Constant(10, typeof(int?)), 
    Expression.Constant(null, typeof(int?))
);
Run Code Online (Sandbox Code Playgroud)