我一直在编程,假设在C#4.0中调用方法时,为参数提供名称不会影响结果,除非这样做是"跳过"一个或多个可选参数.
所以我发现以下行为有点惊讶:
给定一个获取a的方法Func<T>,执行它并返回结果:
public static T F<T>(Func<T> f)
{
return f();
}
Run Code Online (Sandbox Code Playgroud)
以及上述方法可见的另一种方法:
static void Main()
{
string s;
Run Code Online (Sandbox Code Playgroud)
调用F(没有命名参数)编译没有任何问题:
s = F<string>(() => "hello world"); // with explicit type argument <string>
s = F(() => "hello world"); // with type inference
Run Code Online (Sandbox Code Playgroud)
当使用命名参数时......
s = F<string>(f: () => "hello world");
Run Code Online (Sandbox Code Playgroud)
...使用显式类型参数的上述代码行仍然可以编译而没有问题.也许并不太令人惊讶,如果安装了ReSharper,它将表明"类型参数规范是多余的".
但是,删除类型参数时...
s = F(f: () => "hello world");
Run Code Online (Sandbox Code Playgroud)
C#编译器将报告此错误:
无法从用法推断出方法'Program.F(System.Func)'的类型参数.尝试显式指定类型参数.
对于命名参数和类型推断之间的这种交互,是否有逻辑解释?
这种行为是否记录在语言规范的某处?
我明白,根本没有必要为这个论点命名.但是,我在一个更复杂的场景中发现了这种行为,我认为在我的方法调用中为参数命名以用于内部文档目的可能是有意义的.我不是问如何解决这个问题.我试图理解一些语言的细节.
为了使事情更有趣,我发现以下所有编译都没有问题:
Func<string> func = () => "hello world";
s = F<string>(func);
s = F(func); …Run Code Online (Sandbox Code Playgroud) 我最近一直在玩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)