我有以下Linq
var seq =
GetCollectionA()
.Concat(GetCollectionB())
.Concat(GetCollectionC())
.FirstOrDefault();
如果GetCollectionA()
返回了一些对象,则包裹在Concat
中的其他两个方法将仍然运行,并且一无所获。这些方法中的每一个都返回一个实际的数组,而不是真正的Linq友好的Enumerable。我的目标是在实际需要时对Concat
进行参数评估。如果Concat允许像这样延迟加载lambda表达式,那会不会很好?
var seq =
GetCollectionA()
.Concat(() => GetCollectionB())
.Concat(() => GetCollectionC())
.FirstOrDefault();
我正在考虑以下解决方法,如果在第一个集合中找到该元素,此方法是否可以工作,并且不调用后续的集合方法?
var seq =
GetCollectionA()
.Concat(Enumerable.Range(1, 1).SelectMany(_ => GetCollectionB()))
.Concat(Enumerable.Range(1, 1).SelectMany(_ => GetCollectionC()))
.FirstOrDefault();
Concat
是否会实际上对序列进行迭代,而不是将其放入迭代管道中?
有更好的方法吗?
答案 0 :(得分:1)
考虑使用这种方法一次枚举一个集合:
关键是#include "multiboot.h"
typedef int (*initcall_t)(void);
#define __section(S) __attribute__((__section__(#S)))
#define __used __attribute__((__used__))
#define __init __section(.init.text)
static int __init myFunc(void)
{
for (int i = 0; i < 3; i++)
;
return 0;
}
void kernel_main(multiboot_info_t *mbd, unsigned int magic)
{
magic = magic;
mbd = mbd;
while (1)
;
}
static __used initcall_t __initcall_myFunc6 __section(".initcall6.init") = myFunc;
接受SmartConcat
,而不是方法调用(当前正在使用)的结果。因此,一旦找到匹配项,它就可以停止执行。
Func
或者,如果要处理引用类型,请考虑:
using System;
using System.Collections.Generic;
using System.Linq;
namespace Test
{
static class ExtraLINQ
{
public static IEnumerable<T> SmartConcat<T>(this IEnumerable<T> source, params Func<IEnumerable<T>>[] extras)
{
foreach (var entry in source)
yield return entry;
foreach (var laterEntries in extras)
{
foreach (var laterEntry in laterEntries())
{
yield return laterEntry;
}
}
}
}
class Program
{
static void Main(string[] args)
{
// Executes both functions
var first = GetCollectionA().Concat(GetCollectionB()).FirstOrDefault();
Console.WriteLine(first);
// Executes only the first
var otherFirst = GetCollectionA().SmartConcat(GetCollectionB).FirstOrDefault();
Console.WriteLine(otherFirst);
Console.ReadLine();
}
private static IEnumerable<int> GetCollectionA()
{
var results = new int[] { 1, 2, 3 };
Console.WriteLine("GetBob");
return results;
}
private static IEnumerable<int> GetCollectionB()
{
var results = new int[] { 4,5,6 };
Console.WriteLine("GetBob4");
return results;
}
}
}
答案 1 :(得分:-1)
显然我的丑陋骇客作品有用。
public static void Main()
{
Console.WriteLine("Hello World");
var seq = GetNumbers().Concat(Enumerable.Range(1, 1).SelectMany(_ => GetNumbers())).FirstOrDefault();
Console.WriteLine(seq);
}
static int[] GetNumbers()
{
Console.WriteLine("GetNumbers called");
return new[]{1, 2, 3};
}
}
GetNumbers
只被叫过一次
Hello World
GetNumbers called
1