使用动态函数参数进行 C# 编译器类型推断



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

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

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

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

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

编辑:经过编辑以明确使用没有重载的方法会发生这种情况

你是对的,编译器可以推断出所有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);

语义完全改变;在使用者有一个安全的强类型变量之前,现在他突然有一个潜在的不安全隐式强制转换,可以在运行时爆炸。

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

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

int MyMethod(int a)
{
return 5;
}
double MyMethod(string a)
{
return 6.0;
}

然后编写以下代码:

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

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

最新更新