从this question我5分钟前问过,很明显以下代码抛出异常,说明
未处理的例外情况: System.InvalidOperationException:The 二进制运算符Equal未定义 对于类型 'System.Nullable`1 [System.Int32]'和 'System.Int32'。
代码
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();
}
但是,此代码使用Expression.Constant
中明确列出的类型可以正常工作
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();
}
问题是,为什么 Expression.Constant
无法隐式地从int?
转换为... int?
答案 0 :(得分:15)
表达式树在较低级别上工作到正常的源代码 - 您可以将它们视为在编译器的输出级而不是输入。因此,虽然在C#中存在从int
到int?
的隐式转换,但只要编译器将其用于普通方法,就必须在IL中表示转换...因此它也必须存在于表达树表示。
话虽如此,你的例子有点不清楚,因为你试图使用int
(即ItemTypeValue.Value
)作为int?
常数的值,我们不要我不知道ItemType
属性的类型是什么。
您希望工作的简短但完整的示例真的会有所帮助。
编辑:好的,我想我现在和你在一起。问题是如果你使用int? foo = 1;
Expression.Constant(foo);
然后调用Expression.Constant(object)
,其中包含foo
的值。此时,Expression.Constant
无法告诉它原来是int?
,因为它现在是一个盒装int
。这就是.NET拳击的工作方式:
int? foo = 1;
object o = foo;
Console.WriteLine(o.GetType()); // Prints System.Int32
Expression.Constant
的重载根据给定的值确定表达式的整体类型 - 因此它创建了一个int
表达式,而你真的想要一个int?
表达式。
为了正确维护类型信息,您必须使用允许您指定类型的重载:
int? foo = 1;
Expression.Constant(foo, typeof(int?));
您的问题仍然不完全清楚哪些代码有效,哪些代码无效,但希望这有助于......