可为null的int的GetType返回与int的GetType相同的

时间:2019-01-07 10:24:08

标签: c# expression nullable func

我有一个将表达式作为参数的函数。表达式的类型为Func<int?>。但是,当对表达式求值时,可为空的int会被解压缩。

请参见以下代码:

using System;
using System.Linq.Expressions;

public class Program
{
    public static void Main()
    {
        var asd = new Asd() { Id = 1 };
        Do(() => asd.Id);
        Console.Read();
    }

    private static void Do<T>(Expression<Func<T>> expr)
    {
        var tType = typeof(T);
        var type = expr.Compile()().GetType();
        Console.Write($"T = {tType.Name}, obj type = {type.Name}");
    }

    class Asd
    {
        public int? Id { get; set; }
    }
}

控制台显示以下输出:

T = Nullable`1, obj type = Int32

为什么会发生这种情况,如何避免这种情况? 不幸的是,我无法提供dotnetfiddle,因为此代码无法在dotnetfiddle中运行。也许是因为表情。

//编辑:

明确说明:我需要属性 Id int?类型,并且需要编译并执行该函数。这里的问题出现在更大的代码段中。此代码只是具有可运行示例的最低要求代码集。

最诚挚的问候

//编辑2:

原来,我的小例子也产生了错误,这让我认为它表明了我的实际问题。但是,当然不是。 我使用GetType()向您展示了函数返回值不是Nullable<int>类型,而是int类型。根据评论中提供的链接,GetType()引发可为null的拆箱,从而返回基础类型。

我真正的问题是另一个可能也有类似原因的问题。 我使用var valueExpr = Expression.Constant(valueFromImport);创建了一个可为空的值int? valueFromImport = ...的常量表达式。稍后,我设置一个表达式,将常量分配给可为空的属性。失败并带有异常:

System.ArgumentException: "Expression of type 'System.Int32' cannot be used for assignment to type 'System.Nullable`1[System.Int32]'"

问题是Expression.Constant似乎也取消了可为空的值的装箱。当我使用var valueExpr = Expression.Constant(valueFromImport, typeof(T));时,一切都会按预期进行。

1 个答案:

答案 0 :(得分:1)

“ int is unpacked”是什么意思? expressio的结果仍然是int?类型,但是您不能通过反射来获得它,这是预期的行为。引用msdn for Nullables

  

在Nullable类型上调用GetType会导致在将类型隐式转换为Object时执行装箱操作。因此,GetType总是返回一个Type对象,该对象代表基础类型,而不是Nullable类型。

无论哪种方式,您的主要问题是什么?结果的类型正确,您仍然可以使用typeof(T)获得它。 GetType的结果不应该妨碍您。