我有一个将表达式作为参数的函数。表达式的类型为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));
时,一切都会按预期进行。
答案 0 :(得分:1)
“ int is unpacked”是什么意思? expressio的结果仍然是int?
类型,但是您不能通过反射来获得它,这是预期的行为。引用msdn for Nullables:
在Nullable类型上调用GetType会导致在将类型隐式转换为Object时执行装箱操作。因此,GetType总是返回一个Type对象,该对象代表基础类型,而不是Nullable类型。
无论哪种方式,您的主要问题是什么?结果的类型正确,您仍然可以使用typeof(T)
获得它。 GetType
的结果不应该妨碍您。