During the working over next version of Camlex.NET library we encountered with the interesting problem: when we tried to construct LessThan expression for our types the following exception was thrown:
The binary operator LessThan is not defined for the types 'System.Object' and 'SomeType'.
SomeType here is the inheritor of the class where operation “<” is defined. But at the same time there is no explicitly defined operator “<” in SomeType it self. Nevertheless it allows you to write the following correct C# code:
This code is successfully compiled and executed, i.e. operator “<” is called for operands of object and SomeType types. However if you will try to construct LessThan expression with left operand of object type and right operand of SomeType type (using Expression.LessThan method), you will get the mentioned exception. If you will use right operand of type BaseType, expression will be constructed correctly. Also you can define operators “<” and “>” directly in SomeType (and use SomeType as 2nd parameter) – expression will also be created. Seems like Expression.LessThan doesn’t search for operators defined in base classes. Instead it searches only in specified class itself (thanks to Vladimir who found the problem).
However there is more elegant solution for the problem which doesn’t require changing of the code. It was crucial for us because as I said we faced with this issue when working on Camlex where we needed to construct expressions like this:
x has SPListItem type which has several indexers, one of them receives string as parameter and returns object. Here is more realistic test:
This code fails because on left operand passed on the line 48 has type object, and right operand has type DataTypes.Text which is subclass of BaseFieldTypeWithOperators and which doesn't has explicitly defined operators in it.
Solution is quite simple: you should use overridden version of Expression.LessThan method which receives 4 parameters:
In last parameter you should specify MethodInfo variable which represents operator “<” from the base class. I.e. the previous example will look like this:
Difference is in lines 17-19: at first we get reference to operator “<” (op_LessThan) and after that we pass it into Expression.LessThan() method. After this expression will be successfully created.