这是我的代码:
protected IEnumerable<Hotel> Hotels;
protected Hotel Hotel;
Hotels = from Hotel hotel in new Hotels()
select hotel;
Response.Write("RES " + Hotels.Count() + "<br />");
if (Hotels.Count() > 0)
{
Hotel = Hotels.First();
}
Response.Write("RES " + Hotels.Count() + "<br />");
Response.Write("RES " + Hotels.Count() + "<br />");
嗯,酒店有1项。但结果是:
RES 1
RES 0
RES 1
为什么呢?似乎.First()
与迭代器混淆了?如何使用IEnumberable修复它? (不使用其他类型的列表,我需要IEnumerable)。
答案 0 :(得分:3)
static void Main(string[] args)
{
IEnumerable<String> Hotels = new List<String>{"sdsfsdf"};
String Hotel;
Console.WriteLine("RES " + Hotels.Count());
if (Hotels.Count() > 0)
{
Hotel = Hotels.First();
}
Console.WriteLine("RES " + Hotels.Count());
Console.WriteLine("RES " + Hotels.Count());
}
打印
RES 1
RES 1
RES 1
正如预期的那样,你是如何填充可枚举的,以及你创建它的类型是什么?
如果你通过未执行的查询来填充这个,你可能会得到这样的奇怪行为,因为它会选择第一个用法(在这种情况下是First()
)。
答案 1 :(得分:3)
这里没有魔力。看起来Hotels
集合中的项目数量在时间上有所变化,可能是一些带有自定义执行的LINQ查询,甚至可能是LINQ-to-SQL。
请显示填写酒店的完整代码。
答案 2 :(得分:1)
“First”方法可能会使迭代器前进到指向第二个元素。第一次调用“Count”然后完成对一个元素序列的迭代,随后的count调用将重新开始迭代。 Count将始终迭代整个序列,因此它是幂等的。您需要一种方法在Hotels.Reset()
之后重置枚举器First()
,以使Count()
行为正确。
最简单的事情可能是自己制作Reset
扩展名,但我无法重现您的问题。如果你有一些系统生成的数据库迭代器,它可能不会自动重置,你可以使用下面的代码。它只是利用你自己的发现,一个Count()
重置迭代器。它将O(n)
完成。
static class Extensions
{
public static void Reset<T>(this IEnumerable<T> toReset )
{
if (toReset != null)
{
int i = toReset.Count();
}
}
}
但我无法重现你的问题:
下面的代码给出了正确的结果。你有自己的枚举器或集合吗?
static void Main(string[] args)
{
var Response = System.Console.Out;
var Hotels = new[]{1, 2, 3, 4};
var Hotel = 0;
Response.Write("RES " + Hotels.Count() + "<br />");
if (Hotels.Count() > 0)
{
Hotel = Hotels.First();
}
Response.Write("RES " + Hotels.Count() + "<br />");
Response.Write("RES " + Hotels.Count() + "<br />");
Console.WriteLine( "Hotel: " + Hotel);
}
答案 3 :(得分:1)
根据底层实现,无法以任何方式重新枚举IEnumerable以返回相同的值。要了解原因,请考虑此示例;
static void Main(string[] args)
{
IEnumerable<int> bop = RandomSequence();
Console.WriteLine(bop.Count());
Console.WriteLine(bop.Count());
}
private static int _seed = 0;
static IEnumerable<int> RandomSequence()
{
var random = new Random(_seed++);
int randomNumber;
while ((randomNumber = random.Next(100)) != 0)
yield return randomNumber;
}
这是一个完全有效的IEnumerable,对Count()的两次调用将计算为两个不同的伪随机值。原因是Count()重新枚举相同的IEnumerable并生成完全不同的随机序列。
如果你想要可重复的枚举,你需要在枚举上调用ToList()
或ToArray
来存储结果,并且每次都以相同的方式从列表/数组中进行所有枚举。