简体   繁体   English

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

[英]Linq and the Equality Operator: Expression of type 'System.Int32' cannot be used for parameter of type 'System.Object'

I'm trying to override the equality (==) operator in C# to handle comparing any type to a custom type (the custom type is really a wrapper/box around null). 我正在尝试覆盖C#中的相等(==)运算符来处理将任何类型与自定义类型进行比较(自定义类型实际上是一个围绕null的包装器/框)。

So I have this: 所以我有这个:

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;
    }
   ...
}

Now if I make a call like: 现在,如果我打电话:

Nothing n = new Nothing();
bool equal = (10 == n);

It works perfectly fine. 它工作得很好。 However, if I try to do this same thing through a Linq expression tree: 但是,如果我尝试通过Linq表达式树执行相同的操作:

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

It throws the exception: 它抛出了异常:

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)

Any ideas on why the base system can convert Int32 to Object, but Linq can't, or how I can fix this? 关于为什么基本系统可以将Int32转换为Object的任何想法,但Linq不能,或者我如何解决这个问题?

This whole thing stared because Linq also can't compare Int32 to Object in the first place: 整个事情盯着看,因为Linq也无法首先将Int32与Object进行比较:

exp = Expression.Equal(
    Expression.Constant(10), 
    Expression.Constant(null)
);

Throws an exception stating that there is no comparison operator for "System.Int32" and "System.Object". 引发异常,指出“System.Int32”和“System.Object”没有比较运算符。


Quick followup: 快速跟进:

The following do work without issue: 以下工作没有问题:

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)
);

So specifically casting everything to object. 所以特意将一切都投射到物体上 So does Linq just not handle inheritance internally? 那么Linq内部没有处理继承吗? Thats pretty annoying... 多奇怪啊...


Followup #2: 后续#2:

I also tried using a custom comparison method: 我也尝试过使用自定义比较方法:

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;
    }

This too throws an exception: 这也引发了一个例外:

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)

But again casting everything directly to object works: 但是再次将所有内容直接投射到对象上:

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

So I guess I have my workaround... cast everything to object and use a custom comparison method. 所以我想我有我的解决方法......将所有内容都转换为对象并使用自定义比较方法。 I'm still surprised Linq doesn't do the conversion automatically as normal C# does. 我仍然感到惊讶Linq没有像普通C#那样自动进行转换。

What is wrong with null? null有什么问题? Re the missing int vs null , try int? 重新删除int vs null ,尝试int? :

exp = Expression.Equal(
    Expression.Constant(10, typeof(int?)), 
    Expression.Constant(null, typeof(int?))
);

You should take a look at this article to check for a nullable type. 您应该查看本文以检查可以为空的类型。

http://msdn.microsoft.com/en-us/library/ms366789.aspx http://msdn.microsoft.com/en-us/library/ms366789.aspx

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 类型'System.Int32'的表达式不能用于方法'Boolean Equals(System.Object)'的'System.Object'类型的参数 - Expression of type 'System.Int32' cannot be used for parameter of type 'System.Object' of method 'Boolean Equals(System.Object)' 类型'System.Int32'的表达式不能用于方法'Boolean Equals(System.Object)'的类型'System.Object'的参数 - Expression of type 'System.Int32' cannot be used for parameter of type 'System.Object' of method 'Boolean Equals(System.Object)' 类型'System.Int32'的表达式不能用于返回类型'System.Object' - Expression of type 'System.Int32' cannot be used for return type 'System.Object' 类型'System.Nullable`1 [System.Int32]'的表达式不能用于类型'System.Int32'\\ r \\ n的构造函数参数名称:arguments [0] - Expression of type 'System.Nullable`1[System.Int32]' cannot be used for constructor parameter of type 'System.Int32'\r\nParameter name: arguments[0] 无法将类型“ System.Int32”强制转换为类型“ System.Object”。 LINQ to Entities仅支持强制转换EDM基本类型或枚举类型 - Unable to cast the type 'System.Int32' to type'System.Object'. LINQ to Entities only supports casting EDM primitive or enumeration types Expression.Convert:'System.Int64'类型的对象无法转换为'System.Int32'类型 - Expression.Convert: Object of type 'System.Int64' cannot be converted to type 'System.Int32' “System.Int32”类型的ParameterExpression不能用于“System.String”类型的委托参数 - ParameterExpression of type 'System.Int32' cannot be used for delegate parameter of type 'System.String' “System.Int64”类型的表达式不能用于返回类型“System.Object” - Expression of type 'System.Int64' cannot be used for return type 'System.Object' 'System.Int16'类型的表达式不能用于返回类型'System.Object' - Expression of type 'System.Int16' cannot be used for return type 'System.Object' 无法将类型为“WhereListIterator`1[System.Object]”的对象转换为类型“System.Collections.Generic.IEnumerable`1[System.Int32]” - Unable to cast object of type 'WhereListIterator`1[System.Object]' to type 'System.Collections.Generic.IEnumerable`1[System.Int32]'
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM