Dav*_*eau 32
除非我误解了这个问题,否则以下内容在C#4中似乎对我有用:
public static class Defines
{
public static T Identity<T>(T pValue)
{
return pValue;
}
...
Run Code Online (Sandbox Code Playgroud)
然后,您可以在示例中执行以下操作:
var result =
enumerableOfEnumerables
.SelectMany(Defines.Identity);
Run Code Online (Sandbox Code Playgroud)
除了在Defines.Identity
任何地方使用,你都可以使用看起来像的lambda x => x
.
Jon*_*eet 30
注意:这个答案对于C#3是正确的,但在某些时候(C#4?C#5?)类型推断得到了改进,因此可以很容易地使用IdentityFunction
下面所示的方法.
不,没有.它必须是通用的,首先是:
public static Func<T, T> IdentityFunction<T>()
{
return x => x;
}
Run Code Online (Sandbox Code Playgroud)
但是类型推断不起作用,所以你必须这样做:
SelectMany(Helpers.IdentityFunction<Foo>())
Run Code Online (Sandbox Code Playgroud)
这比很丑陋x => x
.
另一种可能性是你在扩展方法中包装它:
public static IEnumerable<T> Flatten<T>
(this IEnumerable<IEnumerable<T>> source)
{
return source.SelectMany(x => x);
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,随着它的通用方差,它可能会在C#3中的各种情况下犯规......它不适List<List<string>>
用于例如.你可以使它更通用:
public static IEnumerable<TElement> Flatten<TElement, TWrapper>
(this IEnumerable<TWrapper> source) where TWrapper : IEnumerable<TElement>
{
return source.SelectMany(x => x);
}
Run Code Online (Sandbox Code Playgroud)
但是,我再次提到了类型推断问题,我怀疑......
编辑:回应评论......是的,C#4使这更容易.或者更确切地说,它使第Flatten
一种方法比在C#3中更有用.这是一个在C#4中工作的例子,但在C#3中不起作用,因为编译器无法转换List<List<string>>
为IEnumerable<IEnumerable<string>>
:
using System;
using System.Collections.Generic;
using System.Linq;
public static class Extensions
{
public static IEnumerable<T> Flatten<T>
(this IEnumerable<IEnumerable<T>> source)
{
return source.SelectMany(x => x);
}
}
class Test
{
static void Main()
{
List<List<string>> strings = new List<List<string>>
{
new List<string> { "x", "y", "z" },
new List<string> { "0", "1", "2" }
};
foreach (string x in strings.Flatten())
{
Console.WriteLine(x);
}
}
}
Run Code Online (Sandbox Code Playgroud)
使用C#6.0并且如果您引用FSharp.Core,您可以:
using static Microsoft.FSharp.Core.Operators
Run Code Online (Sandbox Code Playgroud)
然后你可以自由地做:
SelectMany(Identity)
Run Code Online (Sandbox Code Playgroud)
使用 C# 6.0 事情变得更好了。我们可以按照@Sahuagin 建议的方式定义 Identity 函数:
static class Functions
{
public static T It<T>(T item) => item;
}
Run Code Online (Sandbox Code Playgroud)
然后在使用它SelectMany
的using static
构造函数:
using Functions;
...
var result = enumerableOfEnumerables.SelectMany(It);
Run Code Online (Sandbox Code Playgroud)
我认为这样看起来非常简洁。我还发现 Identity 函数在构建字典时很有用:
class P
{
P(int id, string name) // sad, we are not getting Primary Constructors in C# 6.0
{
ID = id;
Name = id;
}
int ID { get; }
int Name { get; }
static void Main(string[] args)
{
var items = new[] { new P(1, "Jack"), new P(2, "Jill"), new P(3, "Peter") };
var dict = items.ToDictionary(x => x.ID, It);
}
}
Run Code Online (Sandbox Code Playgroud)