为什么C#编译器允许返回值类型与变量类型不匹配?

3

Consider the following code:

static void Main()
{
    dynamic a = 1;
    int b = OneMethod(a);
}

private static string OneMethod(int number)
{
    return "";
}

请注意,b的类型OneMethod的返回类型不匹配。尽管如此,在运行时它仍然构建并抛出异常。 我的问题是为什么编译器允许这样? 或者说这背后的哲学是什么?
这背后的原因可能是编译器不知道调用哪个OneMethod,因为a是动态的。 但是为什么它不能看到只有一个OneMethod呢? 这肯定会在运行时引发异常。

9
动态类型允许包含它的操作绕过编译时类型检查,而是在运行时解决这些操作。 - Tim Schmelter
@TimSchmelter谢谢。事实上我没有在MSDN上搜索。但我的问题是这背后的原因(或哲学)是什么? - serdar
3
我猜你需要问E.Lippert,他可能会回答:“如果你使用dynamic,编译器将不再负责检查变量或任何相关的表达式。” - Tim Schmelter
1个回答

3
任何具有动态类型操作数的表达式本身都具有动态类型。
因此,您的表达式 OneMethod(a) 返回一个动态类型的对象。
因此,您代码的第一部分等同于:
static void Main()
{
    dynamic a = 1;
    dynamic temp = OneMethod(a);
    int b = temp;
}

一种论证这在你的情况下为什么是明智的方法,取决于你是否认为编译器应该根据添加下面的方法的时间来改变那一行的行为。
private static T OneMethod<T>(T number)

现在编译器在运行时才知道返回的类型,甚至不知道调用哪个方法:泛型还是非泛型。如果在第一种情况下将赋值标记为编译错误,然后通过添加完全不同的方法将其移动到运行时错误,你会感到惊讶吗?

1
但是 a 可以有什么值 - 会改变 OneMethod 的返回类型呢? - Jens Kloster
@JensKloster 看一下编辑。通常编译器无法知道返回的类型,因为这意味着它应该在第一次选择正确的方法。但是要做到这一点,您需要知道编译器无法知道的参数类型(即通过将类型声明为动态来告诉编译器不感兴趣)。 - Rune FS
@RuneFS:你有证实你第一句话的来源(文档或C#规范)吗? - Tim Schmelter
我会说它是规范的7.2节。尽管上面可能有过度解释。 - Rune FS

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