【发布时间】:2011-09-16 02:49:21
【问题描述】:
我第一次在 Anomaly 上遇到了一些问题,使用 var 关键字 bit me。
采取这个非常简单的方法
public static Int32? GetNullableInt32(Int32 num)
{
return new Nullable<Int32>(num);
}
现在我们可以使用dynamic 参数调用此方法,一切都会按预期进行。
public static void WorksAsAdvertised()
{
dynamic thisIsAnInt32 = 42;
//Explicitly defined type (no problems)
Int32? shouldBeNullableInt32 = GetNullableInt32(thisIsAnInt32);
Console.Write(shouldBeNullableInt32.HasValue);
}
但是,通过使用隐式类型声明 shouldBeNullableInt32,结果与 我 的预期相差甚远。
public static void BlowsUpAtRuntime()
{
dynamic thisIsAnInt32 = 42;
//Now I'm a dynamic{int}... WTF!!!
var shouldBeNullableInt32 = GetNullableInt32(thisIsAnInt32);
//Throws a RuntimeBinderException
Console.Write(shouldBeNullableInt32.HasValue);
}
返回值不是Nullable<Int32>,而是被视为动态类型。即便如此,底层的Nullable<T> 也不会被保留。由于System.Int32 没有名为HasValue 的属性,因此会抛出RuntimeBinderException。
我会非常很想听到有人能真正解释正在发生的事情(而不仅仅是猜测)。
两个问题
- 当
GetNullableInt32的返回类型清楚地返回Nullable<Int32>时,为什么shouldBeNullableInt32会被隐式键入为动态? - 为什么底层
Nullable<Int32>没有被保留?为什么要用dynamic{int}代替? (在这里回答:C# 4: Dynamic and Nullable<>)
更新
Rick Sladkey's answer 和 Eric Lippert's answer 都同样有效。请同时阅读它们:)
【问题讨论】:
-
此外,如果您将
dynamic thisIsAnInt32 = 42;更改为int thisInAnInt32 = 42,问题也会消失。 -
可能与这个问题有关:stackoverflow.com/questions/3728752/c-4-dynamic-and-nullable。至少它解决了为什么不保留底层 Nullable
的原因。 -
@shf301 - 对。我没有在上面的例子中包括那个,因为我觉得它是给定的。删除动态关键字使所有内容都非常明确。我真正想知道的是,为什么使用动态作为方法的参数会导致编译器覆盖看起来应该是无需动脑筋的东西。但是,我对编译器理论知之甚少,对我来说似乎很基础的东西实际上可能是一个非常复杂的问题。
-
看到IL的代码,方法的返回类型改为valueType而不是int32?类型。因此,当您明确指定持有类型时,即 shouldBeNullableInt32 并且因为 int32 是 valuetype 的后代。因此,事情进展顺利。但是当你说 var 时,这里的事情并不明确。我猜返回类型仍然是值类型。但令我惊讶的是,如果你对它执行 GetType,你会得到 int32 n 而不是 valuetype。但是,嘿,var item 上的 hasvalue 应该给你例外,对吧?
标签: c# dynamic compiler-construction