【发布时间】:2017-10-02 14:40:00
【问题描述】:
鉴于这个简短的示例程序:
static void Main(string[] args)
{
Console.WriteLine(Test("hello world"));
}
private static int Test(dynamic value)
{
var chars = Chars(value.ToString());
return chars.Count();
}
private static IEnumerable<char> Chars(string str)
{
return str.Distinct();
}
运行时会产生类似如下的异常:
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: ''object' does not contain a definition for 'Count''
意思是编译器选择dynamic 作为chars 变量的首选类型。
考虑到动态不是从Chars 方法返回的,是否有任何理由不选择IEnumerable<char> 作为具体类型?只需手动将类型更改为 IEnumerable<char> 即可解决问题,但我想知道为什么 dynamic 在这种情况下是默认值?
编辑
我可能使用了比必要的更复杂的示例。看来这里问的问题:
Anomaly when using 'var' and 'dynamic'
提供了更简洁的示例和一些关于它为何以这种方式工作的见解。
https://blogs.msdn.microsoft.com/ericlippert/2012/11/05/dynamic-contagion-part-one/
描述编译器如何处理动态。
【问题讨论】:
-
我认为这与
value成为dynamic有关,将其更改为string无需修改Chars即可解决问题。我不知道为什么,我也很想知道。 -
使用
dynamic参数,在运行时解决重载。因此,当您调用Chars()时,它拒绝在编译时猜测实际调用的是什么方法。 -
离开
.ToString()会发生什么? -
编译器对 ToString() 一无所知。您也可以使用 ToFoo() ,它仍然可以编译。所以一切都被动态绑定,甚至是 Chars() 调用。但是 Count() 是一个扩展方法,DLR 不会找到它们。最简单的解决方法是使用
(string)value.ToString()帮助编译器正确处理。 -
@HenkHolterman 它会失败并出现同样的异常。
标签: c#