带有动态函数参数的C#编译器类型推断

时间:2017-02-24 09:26:42

标签: c# var type-inference

当我调用一个函数并用dynamic替换其中一个参数时,编译器会将函数结果推断为动态。我不明白为什么会这样。

示例:a的推断类型是动态的,因此此代码编译,但当然在运行时因RuntimeBinderException而失败:

dynamic b = "";
var a = MethodWithoutOverloads("", b);
a.DoesNotExist();

...

public string MethodWithoutOverloads(string a, string b) { ... }

有人知道为什么推断的类型不是函数的返回类型?

编辑:编辑以明确这种情况发生在没有重载的方法

2 个答案:

答案 0 :(得分:1)

你是正确的,编译器可以推断所有String.Format重载返回string,因此推断a必须是一个字符串无论b到底是什么。

事实是编译器不这样做。它解决了一般情况,这很好,并且因为具有不同返回类型的重载在C#中有效,它只是将返回类型指定为动态并让运行时计算出来。

回答您的具体问题,

public string MethodWithoutOverloads(string a, string b) { ... }
dynamic a = "";
var result = MethodWithoutOverloads(a, a); // result is dynamic.

让我们想象一下编译器决定resultstring并且你向你的图书馆西边发布。然后,稍后,您决定添加具有以下签名的重载:

public int MethodWithoutOverloads(int a, int b) { ... } 

现在,result的类型应该是什么?而且,依赖result强烈输入string的现有代码会发生什么?

string result = MethodWithoutOverloads(someDynamicVariable, someOtherDynamicVariable);

语义彻底改变;在消费者拥有一个安全的强类型变量之前,现在他突然有一个可能不安全的隐式强制转换,可能会在运行时爆炸。

答案 1 :(得分:0)

因为编译器不知道将在运行时调用哪个方法。

例如,您可能有两种方法:

int MyMethod(int a)
{
    return 5;
}

double MyMethod(string a)
{
    return 6.0;
}

您编写以下代码:

dynamic myThing = 5;
var myResult = MyMethod(myThing);

考虑到我们已明确表示myThing动态,并且其类型将在运行时确定,我们不知道将调用哪个方法(如果有的话)。因此,我们也不知道返回类型。