10 Stimmen

Linq und der Gleichheitsoperator: Ausdruck vom Typ 'System.Int32' kann nicht für Parameter vom Typ 'System.Object' verwendet werden

Ich versuche, den Gleichheitsoperator (==) in C# zu überschreiben, um einen beliebigen Typ mit einem benutzerdefinierten Typ zu vergleichen (der benutzerdefinierte Typ ist wirklich ein Wrapper/Box um null).

Also habe ich das hier:

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

Wenn ich nun einen Anruf tätige wie:

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

Es funktioniert einwandfrei. Wenn ich jedoch versuche, das Gleiche über einen Linq-Ausdrucksbaum zu tun:

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

Er löst die Ausnahme aus:

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)

Irgendwelche Ideen, warum das Basissystem Int32 in Object konvertieren kann, aber Linq kann nicht, oder wie ich dies beheben kann?

Diese ganze Sache starrte, weil Linq auch nicht Int32 zu Object in erster Linie vergleichen kann:

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

Wirft eine Ausnahme, die besagt, dass es keinen Vergleichsoperator für "System.Int32" und "System.Object" gibt.


Kurze Nachbereitung:

Die folgenden funktionieren ohne Probleme:

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

Also gezielt alles auf Objekt werfen. Behandelt Linq die Vererbung also einfach nicht intern? Das ist ziemlich ärgerlich...


Follow-up #2:

Ich habe auch versucht, eine benutzerdefinierte Vergleichsmethode zu verwenden:

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

Auch hier wird eine Ausnahme ausgelöst:

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)

Aber auch hier funktioniert alles direkt als Objekt:

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

Also ich denke, ich habe meine Abhilfe ... alles zu Objekt und verwenden Sie eine benutzerdefinierte Vergleichsmethode. Ich bin immer noch überrascht Linq tut nicht die Konvertierung automatisch als normale C# tut.

9voto

Marc Gravell Punkte 970173

Was ist falsch an der Null? Zu den fehlenden int gegen null , versuchen int? :

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

0voto

Jay Pete Punkte 3915

Sie sollten einen Blick auf diesen Artikel werfen, um zu prüfen, ob ein nullbarer Typ vorliegt.

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X