简体   繁体   English

IEnumerable的 <Func<T,S> &gt;和LINQ类型推断

[英]IEnumerable<Func<T,S>> and LINQ type inference

C# compiler can correctly infer type of s (string) in these snippets: C#编译器可以正确地推断这些片段中的s(字符串)类型:

 Func<int, string, string> f1 = (n, s) => s.Substring(n);
 Func<int, Func<string, string>> f2 = n => s => s.Substring(n);

But it can't in this one [1]: 但它不能在这一个[1]:

 var numbers = Enumerable.Range(1, 10);
 IEnumerable<Func<string, string>> fs = numbers.Select(n => s => s.Substring(n));

To make it work one has to do something like this: 为了使它工作,必须做这样的事情:

var fs = numbers.Select(n => new Func<string, string>(s => s.Substring(n));

or 要么

var fs = numbers.Select(f2);

And the question is - why type inference doesn't work in [1] if all needed information about types is known beforehand? 问题是 - 如果预先知道关于类型的所有必需信息,为什么类型推断在[1]中不起作用?

All the information about the type isn't known beforehand. 事先知道有关该类型的所有信息。 In your first working snippet, you're telling it on both lines which delegate type you want s => s.Substring(n) to be converted to. 在你的第一个工作片段中,你告诉它在两行代表你希望s => s.Substring(n)转换为的类型。

In your second snippet, the only place where that information is present is in the assignment of the result of Select ... and that isn't used as part of overload and type inference when the compiler is working out what the Select call itself means. 在你的第二个片段中,唯一存在该信息的地方是Select ...的结果赋值,当编译器计算出Select调用本身意味着什么时,它不会被用作重载和类型推断的一部分。

So the options are: 所以选项是:

  • Do it in two steps, using f2 使用f2分两步完成
  • Cast the lambda expression in the Select call, or use a new operator as per your snippet Select调用中转换lambda表达式,或根据您的代码段使用new运算符
  • Provide the type arguments for Select directly: 直接为Select提供类型参数:

     var fs = numbers.Select<int, Func<string, string>>(n => s => s.Substring(n)); 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM