为什么在表达式树中需要转换

Ada*_*kis 7 c# entity-framework expression-trees

从5分钟前我提出的这个问题来看,很明显以下代码抛出异常,说明了这一点

未处理的异常:System.InvalidOperationException:没有为类型'System.Nullable`1 [System.Int32]'和'System.Int32'定义二进制运算符Equal.

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();
    }
Run Code Online (Sandbox Code Playgroud)

但是,此代码具有明确列出的类型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();
    }
Run Code Online (Sandbox Code Playgroud)

现在的问题是,为什么Expression.Constant无法从隐式转换int?为...int?

Jon*_*eet 15

表达式树在较低级别工作到正常的源代码 - 您可以将它们视为在编译器输出级别而不是输入级别工作.因此,虽然有由隐式转换intint?在C#,即转换具有每当编译器将其用于通常的方法是在IL表示...所以它也必须是存在于表达树表示.

话虽如此,你的例子有点不清楚,因为你试图使用int(即ItemTypeValue.Value)作为int?常量的值,我们也不知道ItemType属性的类型是什么.

一个简短而完整的例子,说明你期望的工作真的会有所帮助.

编辑:好的,我想我现在和你在一起.问题是,如果你使用

int? foo = 1;
Expression.Constant(foo);
Run Code Online (Sandbox Code Playgroud)

然后调用Expression.Constant(object)哪个框的值foo.在那一点上,Expression.Constant不能说它原来是一个int?,因为它现在是盒装的int.这就是.NET拳击的工作方式:

int? foo = 1;
object o = foo;
Console.WriteLine(o.GetType()); // Prints System.Int32
Run Code Online (Sandbox Code Playgroud)

那个重载Expression.Constant决定了表达式的整体类型 - 它给出的值 - 所以它创建了一个int表达式,而你真的想要一个int?表达式.

为了正确维护类型信息,您必须使用允许您指定类型的重载:

int? foo = 1;
Expression.Constant(foo, typeof(int?));
Run Code Online (Sandbox Code Playgroud)

从您的问题中仍然不完全清楚哪些代码有效,哪些代码无效,但希望这有助于......