Próbuję przesłonić operatora równości (==) w języku C#, aby poradzić sobie z porównywaniem dowolnego typu z typ niestandardowy (typ niestandardowy to tak naprawdę opakowanie/pudełko o wartości zerowej).Linq i operator równości: wyrażenie typu "System.Int32" nie może być używane dla parametru typu "System.Object"
Więc mam to:
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;
}
...
}
Teraz gdybym wykonać połączenie jak:
Nothing n = new Nothing();
bool equal = (10 == n);
to działa perfekcyjnie. Jednakże, jeśli staram się robić to samo przez LINQ drzewa wyrażenie:
exp = Expression.Equal(
Expression.Constant(10),
Expression.Constant(new Nothing(), typeof(Nothing))
);
To rzuca wyjątek:
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)
Wszelkie pomysły, dlaczego system bazowy może konwertować Int32 do obiektu, ale LINQ nie mogę lub jak mogę to naprawić?
To wszystko patrzył bo Linq też nie można porównywać Int32 do obiektu w pierwszej kolejności:
exp = Expression.Equal(
Expression.Constant(10),
Expression.Constant(null)
);
Zgłasza wyjątek, stwierdzając, że nie ma operatora porównania dla „System.Int32” i „system. Obiekt".
Szybkie nawiązanie:
Poniższy zrobić pracę bez problemu:
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)
);
Więc specjalnie rzucając wszystko sprzeciwu. Czy Linq po prostu nie zajmuje się dziedziczeniem wewnętrznie? Ów dość irytujące ...
Followup # 2:
Próbowałem też stosując metodę porównawczą niestandardowe:
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;
}
To też zgłasza wyjątek:
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)
Ale ponownie rzucając wszystko bezpośrednio na obiekt działa:
exp = Expression.Equal(
Expression.Constant(10, typeof(object)),
Expression.Constant(null, typeof(object)),
false,
this.GetType().GetMethod("ValueEquals", BindingFlags.Public | BindingFlags.Static)
);
Sądzę, że mam moje obejście ... rzucić wszystko do obiektu i użyć niestandardowej metody porównania. Nadal jestem zaskoczony, że Linq nie dokonuje konwersji automatycznie, tak jak robi to normalne C#.
"Czy Linq po prostu nie zajmuje się dziedziczeniem wewnętrznie?To dość denerwujące ... "Tak, jest to denerwujące, ale nie bez powodu: biblioteki drzewek wyrażeń działają z wyrażeń zarówno z C#, jak i VB, i, o ile to możliwe, z każdego innego języka, który ma tego rodzaju wyrażenia. upiekliśmy zasady konwersji C# na kod, który zajmował się rozwiązywaniem równości, a następnie moglibyśmy zrobić coś niewłaściwego dla wyrażeń, które pochodziły z VB, więc nie robimy żadnego - musisz podać jednoznaczne wyrażenia, aby rozdzielczość była językiem . -agnostic –
(dodane myśl re swoim komentarzu) –
Cóż, nie będzie lepiej autorytet w tej sprawie niż Eric Lippert –