Nota: questa risposta è stata corretta per C# 3, ma ad un certo punto (C# 4 C# 5?) Inferenza di tipo migliorato in modo che il metodo IdentityFunction
mostrato sotto può essere facilmente utilizzato.
No, non c'è. Avrebbe dovuto essere generico, per cominciare:
public static Func<T, T> IdentityFunction<T>()
{
return x => x;
}
Ma poi inferenza di tipo non avrebbe funzionato, in modo che ci si deve fare:
SelectMany(Helpers.IdentityFunction<Foo>())
che è molto più brutto di x => x
.
Un'altra possibilità è che si avvolge questo in un metodo di estensione:
public static IEnumerable<T> Flatten<T>
(this IEnumerable<IEnumerable<T>> source)
{
return source.SelectMany(x => x);
}
Purtroppo con varianza generica così com'è, che potrebbe cadere fallo di vari casi in C# 3 ... non sarebbe essere applicabile a List<List<string>>
per esempio. Si potrebbe rendere più generico:
public static IEnumerable<TElement> Flatten<TElement, TWrapper>
(this IEnumerable<TWrapper> source) where TWrapper : IEnumerable<TElement>
{
return source.SelectMany(x => x);
}
Ma ancora una volta, hai poi ottenuto problemi di inferenza di tipo, ho il sospetto ...
EDIT: Per rispondere alle osservazioni ... sì, C# 4 marche questo più facile. O meglio, si fa la prima Flatten
metodo più utile di quanto non sia in C# 3. Ecco un esempio che funziona in C# 4, ma non funziona in C# 3 perché il compilatore non può convertire 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);
}
}
}
Non capirò mai perché non includono i combinatori SKI in C#. –