泛型类型推理与活力的工作? [英] Generic type inference not working with dynamic?
问题描述
我最近在玩海量,一个Micro-ORM返回的IEnumerable<的集合;动态方式>
I have recently been playing with Massive, a Micro-ORM which returns collections of IEnumerable<dynamic>.
我发现了一个意想不到的问题,当我试图查询的一种使用LINQ的集合。
I discovered an unexpected issue when I tried to query one of those collections using LINQ.
虽然编译器似乎已经没有任何问题的工作指出,即使的String.Format返回一个字符串的时候传递给它的论据之一是声明为动态...
While the compiler seems to have no issues whatsoever to work out that string.Format returns a string even when one of the arguments passed to it is declared as dynamic...
dynamic dynamicString = "d"; // just using a string here for simplicity, same problem occurs with any other type
string explicitString = string.Format("string is {0}", dynamicString); // works without issues
...这似乎并不能够推断事实以下情形:
...it doesn't appear to be able to infer that fact in the following scenario:
IEnumerable<string> strings = new[] { "a", "b", "c" };
IEnumerable<dynamic> dynamics = strings;
IEnumerable<string> output = dynamics.Select(d => string.Format("string is {0}", d)); // compiler error on this line
编译器会抱怨:
The compiler complains:
"Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<dynamic>' to 'System.Collections.Generic.IEnumerable<string>'. An explicit conversion exists (are you missing a cast?)"
由于编译器应该能够推断出我的lambda表达式返回一个字符串,我本来期望它也推断选择的TResult应该是字符串类型(而不是动态)。
Since the compiler should be able to infer that my lambda expression returns a string, I would have expected it to also infer that the TResult of the Select should be of type string (and not dynamic).
这是很容易通过指定修复在TSource和TResult明确如下:
It was easy to fix by specifying the TSource and TResult explicitly like this:
IEnumerable<string> output2 = dynamics.Select<dynamic, string>(d => string.Format("string is {0}", d)); // works !!!
或者,我可以把结果赋值给一个IEnumerable<动态> ...
Or I could assign the result to an IEnumerable<dynamic>...
IEnumerable<dynamic> output3 = dynamics.Select(d => string.Format("string is {0}", d)); // also works
我也证实,当我代替我的IEnumerable<不会出现此问题;动态> ;有一个IEnumerable<对象>
I have also confirmed that this problem does not occur when I replace my IEnumerable<dynamic> with an IEnumerable<object>:
IEnumerable<object> objects = strings;
IEnumerable<string> output4 = objects.Select(o => string.Format("string is {0}", o)); // works
有趣的是,即使以下工作:
And interestingly even the following works:
IEnumerable<string> output5 = dynamics.Select(d => string.Format("string is {0}", (object)d)); // works
IEnumerable<string> output6 = dynamics.Select(d => string.Format("string is {0}", (string)d)); // works
任何人能解释这是怎么回事呢? ?这是C#编译器的一个已知限制或有我发现了另一个错误
Can anybody explain what's going on here? Is this a know limitation of the C# compiler or have I found yet another bug?
推荐答案
您需要:
IEnumerable<string> output = dynamics.Select(d => (string)string.Format(
"string is {0}", d));
它无法推断返回类型为字符串
,因为动态
意味着它必须承担回报动态
,如果有更合适的超载的的String.Format
为提供(用不同的返回类型)的特定类型。即使我们知道,否则,该规范为动态
会同意我们的观点,P通过增加一个显式类型转换回字符串
。我们做的返回类型明确
It can't infer the return type is string
, because the dynamic
means it has to assume the return is dynamic
, in case there is a more suitable overload of string.Format
for the specific type supplied (with a different return type). Even if we know otherwise, the spec for dynamic
will disagree with us ;p By adding an explicit cast back to string
we make the return type clear.
就个人而言,我看不出使用了动态
在这里;你还不如用对象
,那么它是不是摆在首位的问题:
Personally, I see no use for dynamic
here; you might as well use object
, then it isn't an issue in the first place:
IEnumerable<string> strings = new[] { "a", "b", "c" };
IEnumerable<object> dynamics = strings;
IEnumerable<string> output = dynamics.Select(d => string.Format(
"string is {0}", d));
(或实际上,保留为的IEnumerable<串>
)我假定你有一些其他原因使用动态
,是不是在这个例子中可见。
(or indeed, leave as IEnumerable<string>
) I assume you have some other reason to use dynamic
that isn't visible in this example.
这篇关于泛型类型推理与活力的工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!