为什么这里的类型是System.Object?

3

以下是一些代码:

Func<dynamic> f1 = new Func<dynamic>(() => 10);
Func<int> f2 = () => 10;

Console.Write(f1.Method.ReturnType);
Console.Write(" and " + f2.Method.ReturnType );

输出结果: System.Object 和 System.Int32

我的问题是:

为什么DLR推断的dynamic类型(用于dynamic的类型)在这里是System.Object而不是System.Int32?这并不是很合逻辑,因为它还涉及将Int32结构装箱为对象。

据我所知,在这里检查类型时,我们在执行时间上动态地执行,因为我们使用Reflection。 所以DLR当时已知它是int,但由于某种原因,它将其装箱为Object...为什么?

我试图在SO和Google上找到任何关于此的信息,但我找不到任何解释所有内容的答案。


1
不确定f1.GetType().GetGenericArguments().First()是什么,但更好的获取返回类型的方法是f1.Method.ReturnType - M.kazem Akhgary
@M.kazemAkhgary 您是正确的,我们可以两种方式都实现,它们产生相同的输出对象和Int32... 我不明白为什么是Object... - Fabjan
正如Patrick Hofman所说,编译器不知道类型,因为函数() => 10尚未执行。 - M.kazem Akhgary
不行。为了更好地理解,请尝试转换 (Func<int>)(() => 10)。这不能分配给 Func<dynamic>。这意味着 Func<int>Func<dynamic> 是完全不同的东西。由于 Func<dynamic> 没有被执行,因此即使在运行时也不知道返回类型。如果您执行它,您将获得正确的结果。尝试 f1().GetType(),您会看到它打印出 System.Int32。方法信息保存在 Method 属性中。那应该是编译时。所以对于动态类型,f1.Method.ReturnType 是对象,而对于整数则是 Int。 - M.kazem Akhgary
@M.kazemAkhgary 感谢您的有用评论。我似乎忘记了静态编译器在处理动态 lambda 表达式时无法推断类型。 - Fabjan
1个回答

7

这里没有推断出任何东西。只是在执行之前不知道其类型,因此给定的类型是object。(静态)编译器不知道类型,因为你还不知道它。它被传递为object,在调用方面又变成了dynamic

对于常规方法也是如此:

Console.Write(typeof(Program).GetMethod("F1").ReturnType);

public static dynamic F1()
{
    return 10;
}

Output:

System.Object


谢谢Patrick,你提出了一个很好的观点。我似乎有点困惑于dynamic如何在“正常方式”下与结构类型一起使用以及它如何与委托一起使用。 - Fabjan
@Fabjan - 请记住,dynamic不是一种类型 - 它只是声明在编译时未知类型的声明。编译器可以用来表示将来任何类型的唯一类型是object。就是这么简单。 - Enigmativity

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接