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 int
to int?
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
(namely ItemTypeValue.Value
) as a value for an int?
constant, and we don't know what the type of the ItemType
property 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
int? foo = 1;
Expression.Constant(foo);
then that calls Expression.Constant(object)
which boxes the value of foo
. At that point, Expression.Constant
can't tell it was originally an int?
, because it's now a boxed int
. That's just the way .NET boxing works:
int? foo = 1;
object o = foo;
Console.WriteLine(o.GetType()); // Prints System.Int32
That overload of Expression.Constant
determines the overall type of the expression from the value that it's given - so it creates an int
expression, whereas you really want an int?
expression.
In order to maintain the type information properly, you have to use the overload which allows you to specify the type:
int? foo = 1;
Expression.Constant(foo, typeof(int?));
It's still not entirely clear from your question which code works and which doesn't, but hopefully that'll help...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With