2017-02-24 88 views
3

当我调用一个函数并用动态替换其中一个参数时,编译器会将函数结果推断为动态。我不明白为什么会发生这种情况。带动态功能参数的C#编译器类型推理

例:推断类型为是动态的,所以这段代码编译,但当然在运行时失败,RuntimeBinderException:

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

...

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

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

编辑:编辑,以明确出现这种情况有没有方法重载

回答

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); 

语义完全变化;在消费者拥有一个安全的强类型变量之前,现在他突然有一个潜在的不安全隐式强制转换,可能会在运行时崩溃。

0

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

例如,你可以有两种方法:

int MyMethod(int a) 
{ 
    return 5; 
} 

double MyMethod(string a) 
{ 
    return 6.0; 
} 

而且你写下面的代码:

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

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

+0

这种情况发生在我有一种方法时,即没有歧义时。 String.Format不是一个好例子,但是当没有歧义时我调用我自己的方法时类型推断也失败。 – Lev

+1

@Lev这是正确的。*技术上*编译器或许能够毫不含糊地将其弄清楚,但我认为这需要更多的工作来获得看似不大的收益。每当“动态”是表达式的一部分时,结果也将通过“动态”。如果你确定知道类型,只需使用变量类型明确而不是使用'var' – Rob

+0

好吧,所以基本上是“我们没有对这种情况实现类型推断”的情况...... – Lev