From this question I asked 5 minutes ago, it’s clear that the following code throws an exception, stating that
Unhandled Exception:
System.InvalidOperationException: The
binary operator Equal is not defined
for the types
‘System.Nullable`1[System.Int32]’ and
‘System.Int32’.
Code
public static void GetResultCollection<T>() {
AccrualTrackingEntities db = new AccrualTrackingEntities();
var result = db.CreateQuery<T>(String.Format("[{0}]", typeof(T).Name + "s"));
int? ItemTypeValue = 1;
var param = Expression.Parameter(typeof(T));
var lambda = Expression.Lambda<Func<T, bool>>(
Expression.Equal(
Expression.Property(param, "ProcInstId"),
Expression.Constant(ItemTypeValue)),
param);
var list = result.Where(lambda).ToList();
}
This code, however, with the type explicitly listed in Expression.Constant does work
class Program {
public static void GetResultCollection<T>() {
AccrualTrackingEntities db = new AccrualTrackingEntities();
var result = db.CreateQuery<T>(String.Format("[{0}]", typeof(T).Name + "s"));
int? ItemTypeValue = 1;
var param = Expression.Parameter(typeof(T));
var lambda = Expression.Lambda<Func<T, bool>>(
Expression.Equal(
Expression.Property(param, "ProcInstId"),
Expression.Constant(ItemTypeValue, typeof(int?))),
param);
var list = result.Where(lambda).ToList();
}
The question is, why is Expression.Constant not able to convert implicitly from int? to … int?
Expression trees work at a lower level to normal source code – you can think of them as working at the level of the output of the compiler rather than the input. So while there’s an implicit conversion from
inttoint?in C#, that conversion has to be represented in IL whenever the compiler uses it for a normal method… so it also has to be present in an expression tree representation.Having said that, your example is somewhat unclear, given that you’re trying to use an
int(namelyItemTypeValue.Value) as a value for anint?constant, and we don’t know what the type of theItemTypeproperty is either.A short but complete example of what you’d expect to work would really help.
EDIT: Okay, I think I’m with you now. The problem is that if you use
then that calls
Expression.Constant(object)which boxes the value offoo. At that point,Expression.Constantcan’t tell it was originally anint?, because it’s now a boxedint. That’s just the way .NET boxing works:That overload of
Expression.Constantdetermines the overall type of the expression from the value that it’s given – so it creates anintexpression, whereas you really want anint?expression.In order to maintain the type information properly, you have to use the overload which allows you to specify the type:
It’s still not entirely clear from your question which code works and which doesn’t, but hopefully that’ll help…