【问题标题】:GetType of nullable int returns same as GetType of int可空 int 的 GetType 返回与 int 的 GetType 相同
【发布时间】:2019-01-07 20:01:53
【问题描述】:

我有一个将表达式作为参数的函数。表达式的类型是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&lt;int&gt; 类型,而是int。根据 cmets 中提供的链接,GetType() 会导致可空对象的拆箱,从而返回基础类型。

我真正的问题是另一个可能有类似原因的问题。 我使用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)); 时,一切都按预期工作。

【问题讨论】:

  • 你正在编译它然后调用它。删除一组()
  • 只需将Console.Write($"T = {tType.Name}, obj type = {type.Name}"); 替换为Console.Write($"T = {tType}, obj type = {type.Name}");,您将获得有关泛型参数类型的信息(提示:您将获得Nullable'1[Int32] 而不仅仅是Nullable'1)。
  • 如果您通过删除 interpolated string 和不必要的 () 来修复它,此代码在 .NET Fiddle 中可以正常工作
  • The problem is that the console shows int32 for the function's result. 阅读我给你的链接。特别阅读问题。尤其要阅读其中的 MSDN 引用。 粗体中的位。我怀疑这可能与您的情况有关并可以解释。

标签: c# expression nullable func


【解决方案1】:

“int 已解包”是什么意思? expressio 的结果仍然是int? 类型,但您无法通过反射得到它,这是预期的行为。引用msdn for Nullables

对 Nullable 类型调用 GetType 会导致在类型隐式转换为 Object 时执行装箱操作。因此 GetType 总是返回一个表示底层类型的 Type 对象,而不是 Nullable 类型。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-20
    • 1970-01-01
    • 2013-09-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多