假设我有这个问题:
int[] Numbers= new int[5]{5,2,3,4,5};
var query = from a in Numbers
where a== Numbers.Max (n => n) //notice MAX he should also get his value somehow
select a;
foreach (var element in query)
Console.WriteLine (element);
运行Numbers
时,foreach
枚举的次数是多少次?
我该如何测试它(我的意思是,编写一个告诉我迭代次数的代码)
答案 0 :(得分:3)
以下是检查计数的方法
void Main()
{
var Numbers= new int[5]{5,2,3,4,5}.Select(n=>
{
Console.Write(n);
return n;
});
var query = from a in Numbers
where a== Numbers.Max (n => n)
select a;
foreach (var element in query)
{
var v = element;
}
}
这是输出
5 5 2 3 4 5 2 5 2 3 4 5 3 5 2 3 4 5 4 5 2 3 4 5 5 5 2 3 4 5
答案 1 :(得分:3)
它将被迭代6次。一次为Where
,每个元素一次为Max
。
用于演示此代码的代码:
private static int count = 0;
public static IEnumerable<int> Regurgitate(IEnumerable<int> source)
{
count++;
Console.WriteLine("Iterated sequence {0} times", count);
foreach (int i in source)
yield return i;
}
int[] Numbers = new int[5] { 5, 2, 3, 4, 5 };
IEnumerable<int> sequence = Regurgitate(Numbers);
var query = from a in sequence
where a == sequence.Max(n => n)
select a;
它将打印“迭代序列6次”。
如果你打算用它来试验其他情况,我们可以制作一个更灵活的更通用的包装器:
public class EnumerableWrapper<T> : IEnumerable<T>
{
private IEnumerable<T> source;
public EnumerableWrapper(IEnumerable<T> source)
{
this.source = source;
}
public int IterationsStarted { get; private set; }
public int NumMoveNexts { get; private set; }
public int IterationsFinished { get; private set; }
public IEnumerator<T> GetEnumerator()
{
IterationsStarted++;
foreach (T item in source)
{
NumMoveNexts++;
yield return item;
}
IterationsFinished++;
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public override string ToString()
{
return string.Format(
@"Iterations Started: {0}
Iterations Finished: {1}
Number of move next calls: {2}"
, IterationsStarted, IterationsFinished, NumMoveNexts);
}
}
这比其他功能有几个优点:
答案 2 :(得分:3)
以下是如何估计枚举集合的快速计数:将集合包装在CountedEnum<T>
中,并在每个yield return
上增加计数器,如下所示 -
static int counter = 0;
public static IEnumerable<T> CountedEnum<T>(IEnumerable<T> ee) {
foreach (var e in ee) {
counter++;
yield return e;
}
}
然后将您的数组声明更改为
var Numbers= CountedEnum(new int[5]{5,2,3,4,5});
运行您的查询,然后打印counter
。对于您的查询,代码打印30(link to ideone),这意味着您的五个项目的集合已被枚举六次。
答案 3 :(得分:1)
迭代次数必须等于query.Count()
。
所以对第一个查询结果中的元素计数。
如果您要询问其他事项,请澄清。
修改强>
澄清之后:
如果您在所提供的代码中搜索迭代的总计数,则会有7
次迭代(针对此具体情况)。
var query = from a in Numbers
where a== Numbers.Max (n => n) //5 iterations to find MAX among 5 elements
select a;
和
foreach (var element in query)
Console.WriteLine (element); //2 iterations over resulting collection(in this question)
答案 4 :(得分:1)
运行foreach时会枚举NUM次
简而言之,您的代码在道德上等同于:
foreach(int a in Numbers)
{
// 1. I've gotten rid of the unnecessary identity lambda.
// 2. Note that Max works by enumerating the entire source.
var max = Numbers.Max();
if(a == max)
Console.WriteLine(a);
}
所以我们列举以下几次:
1
)的序列的一个枚举。Count
)的序列的一个枚举。总的来说,我们列举Count + 1
次。
您可以通过引入本地来提升循环外的2
查询,将其降低到Max
。
我该如何测试它(我的意思是,编写一个告诉我数字的代码 迭代)
使用原始数组并不容易。但是您可以编写自己的可枚举实现(可能包含数组)并向GetEnumerator
方法添加一些检测。或者如果你想深入了解,那就去整个猪,并在MoveNext
和Current
上编写一个包含检测的自定义枚举器。
答案 5 :(得分:1)
通过公共财产计算也产生6.
private static int ncount = 0;
private int[] numbers= new int[5]{5,2,3,4,5};
public int[] Numbers
{
get
{
ncount++;
Debug.WriteLine("Numbers Get " + ncount.ToString());
return numbers;
}
}
这使得倒数降至2 有道理,但我不会想到它。
int nmax = Numbers.Max(n => n);
var query = from a in Numbers
where a == nmax //notice MAX he should also get his value somehow
//where a == Numbers.Max(n => n) //notice MAX he should also get his value somehow
select a;
答案 6 :(得分:0)
它将被迭代6次。一次为Where
,每个元素一次为Max
。
在foreach循环外定义并初始化count
变量,并在循环内将count变量增加为count++
,以获得枚举次数。