Bir*_*erH 4 c# linq generics type-inference dynamic
我最近一直在玩Massive,一个返回IEnumerable <dynamic>集合的Micro-ORM.
当我尝试使用LINQ查询其中一个集合时,我发现了一个意外的问题.
虽然编译器似乎没有任何问题可以解决这个问题,但是即使传递给它的一个参数声明为动态,string.Format也会返回一个字符串...
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
Run Code Online (Sandbox Code Playgroud)
...在以下情况中似乎无法推断出这一事实:
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
Run Code Online (Sandbox Code Playgroud)
编译器抱怨:
"Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<dynamic>' to 'System.Collections.Generic.IEnumerable<string>'. An explicit conversion exists (are you missing a cast?)"
Run Code Online (Sandbox Code Playgroud)
由于编译器应该能够推断出我的lambda表达式返回一个字符串,我本来希望它也推断出Select的TResult应该是string类型(而不是动态的).
通过明确指定TSource和TResult可以很容易地修复:
IEnumerable<string> output2 = dynamics.Select<dynamic, string>(d => string.Format("string is {0}", d)); // works !!!
Run Code Online (Sandbox Code Playgroud)
或者我可以将结果分配给IEnumerable <dynamic> ...
IEnumerable<dynamic> output3 = dynamics.Select(d => string.Format("string is {0}", d)); // also works
Run Code Online (Sandbox Code Playgroud)
我还确认当我用IEnumerable <object>替换我的IEnumerable <dynamic>时不会发生这个问题:
IEnumerable<object> objects = strings;
IEnumerable<string> output4 = objects.Select(o => string.Format("string is {0}", o)); // works
Run Code Online (Sandbox Code Playgroud)
有趣的是,甚至以下工作:
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
Run Code Online (Sandbox Code Playgroud)
谁能解释一下这里发生了什么?这是C#编译器的已知限制还是我发现了另一个错误?
你需要:
IEnumerable<string> output = dynamics.Select(d => (string)string.Format(
"string is {0}", d));
Run Code Online (Sandbox Code Playgroud)
它不能推断返回类型string,因为dynamic它必须假定返回的意思是dynamic,如果string.Format对于所提供的特定类型(具有不同的返回类型)存在更合适的重载.即使我们不知道,规范dynamic也会不同意我们; p通过添加一个明确的强制转换,string我们使返回类型清晰.
就个人而言,我觉得dynamic这里没用; 你不妨使用object,那么它首先不是问题:
IEnumerable<string> strings = new[] { "a", "b", "c" };
IEnumerable<object> dynamics = strings;
IEnumerable<string> output = dynamics.Select(d => string.Format(
"string is {0}", d));
Run Code Online (Sandbox Code Playgroud)
(或者实际上,保留为IEnumerable<string>)我假设您有其他一些使用的原因,dynamic在此示例中不可见.
| 归档时间: |
|
| 查看次数: |
2421 次 |
| 最近记录: |