我发现自己经常使用IEnumerables,以便我可以返回每个结果。有没有办法压缩像这样的东西
foreach (var subSelector in subSelectors)
{
foreach (var node in FindSingle(context, subSelector))
yield return node;
}
要删除内在的foreach?
答案 0 :(得分:61)
这是C#不支持的频繁请求的功能。有关详细信息,请参阅此Connect项目:
建议的语法通常类似于:
public static IEnumerable<T> PreorderTraversal<T>(this BinaryTree<T> root)
{
if (root == null) yield break;
yield return root.Item;
yield foreach root.Left.PreorderTraversal();
yield foreach root.Right.PreorderTraversal();
}
如果您有兴趣使用支持此功能的C#语言,请查看Cω:
http://research.microsoft.com/en-us/um/cambridge/projects/comega/
您可能还想阅读Cω实现者关于该功能的这篇论文:
http://research.microsoft.com/en-us/projects/specsharp/iterators.pdf
如果您对支持此功能的非C#语言感兴趣,请查看“yield!” F#的特点。 (我只是喜欢这个功能的名称是“收益!”)
即使您对理论上的东西不感兴趣,但听起来您将这种情况视为一个实际问题。你还应该阅读Wes Dyer关于有效地进行这种嵌套迭代的技术的文章,而没有“收益预告”:
http://blogs.msdn.com/b/wesdyer/archive/2007/03/23/all-about-iterators.aspx
答案 1 :(得分:17)
不,除非您使用LINQ将yield return
语句完全替换为return
语句,否则不存在。
例如:
return someSet
.Concat(someOtherSet.SelectMany(s => FindSingle(context, s));
答案 2 :(得分:3)
return subSelectors.SelectMany(subselector => FindSingle(context, subSelector));
仅当您的方法中没有任何其他yield return语句时才有效。
答案 3 :(得分:2)
你可以将你的方法分成两部分。鉴于这些扩展方法:
public static class MultiEnumerableExtensions {
public static IEnumerable<T> Pack<T>(this T item) {
yield return item;
}
public static IEnumerable<T> Flatten<T>(
this IEnumerable<IEnumerable<T>> multiList) {
return multiList.SelectMany(x => x);
}
}
使用Eric Lippert的example,它就变成了这个:
public static class BinaryTreeExtensions {
public static IEnumerable<T> PreorderTraversal<T>(this BinaryTree<T> root) {
return PreorderTraversalMulti(root).Flatten();
}
private static IEnumerable<IEnumerable<T>> PreorderTraversalMulti<T>(
this BinaryTree<T> root) {
if (root == null) yield break;
yield return root.Item.Pack(); // this packs an item into an enumerable
yield return root.Left.PreorderTraversal();
yield return root.Right.PreorderTraversal();
}
}
内部方法产生T的可枚举而不是Ts,而外部方法只需要平整这个结果。
答案 4 :(得分:0)
使用Linq的力量!
return subSelectors.SelectMany(s => FindSingle(context, s));
答案 5 :(得分:0)
在C#7.0中,允许使用局部函数,这使我们能够采用一种相当整齐的方法
IEnumerable<T> FlatEnumerable(){
IEnumerable<IEnumerable<T>> NestedEnumerable(){
yield return myEnumerable1;
yield return myEnumerable2;
}
return NestedEnumerable().SelectMany(e => e);
}
https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/local-functions