【发布时间】:2017-06-05 04:01:24
【问题描述】:
链接https://msdn.microsoft.com/en-us/library/bb534631(v=vs.110).aspx中,第三个签名是
// M<S> -> (S -> M<C>) -> (S -> M<C> -> R) -> E<R>
public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(
this IEnumerable<TSource> source,
Func<TSource, IEnumerable<TCollection>> collectionSelector,
Func<TSource, TCollection, TResult> resultSelector
)
第一个具有典型 Monad 绑定函数 M<A> -> (A -> M<B>) -> M<B> 签名的函数不应该足够吗?将resultSelector中的代码合并到collectionSelector中是不是很容易?
MSDN文档给出了一个例子来说明该方法的使用。
class Program
{
static void Main(string[] args)
{
SelectManyEx3();
}
public static void SelectManyEx3()
{
PetOwner[] petOwners =
{ new PetOwner { Name="Higa",
Pets = new List<string>{ "Scruffy", "Sam" } },
new PetOwner { Name="Ashkenazi",
Pets = new List<string>{ "Walker", "Sugar" } },
new PetOwner { Name="Price",
Pets = new List<string>{ "Scratches", "Diesel" } },
new PetOwner { Name="Hines",
Pets = new List<string>{ "Dusty" } } };
// Project the pet owner's name and the pet's name.
var query =
petOwners
.SelectMany(petOwner => petOwner.Pets, (petOwner, petName) => new { petOwner, petName })
.Where(ownerAndPet => ownerAndPet.petName.StartsWith("S"))
.Select(ownerAndPet =>
new
{
Owner = ownerAndPet.petOwner.Name,
Pet = ownerAndPet.petName
}
);
// Print the results.
foreach (var obj in query1)
{
Console.WriteLine(obj);
}
}
}
class PetOwner
{
public string Name { get; set; }
public List<string> Pets { get; set; }
}
但是,var query = ... 可以使用第一个签名的SelectMany 重写如下?
var query = petOwners.SelectMany(o => o.Pets.Select(p => new { petOwner = o, petName =p}))
带有第三个签名的SelectMany 何时真正有用?
【问题讨论】:
-
我认为第三个签名示例比创建 LINQ 子表达式更易于理解和简洁。
-
有例子吗?