假设两个代码段numToGenerate
,min
和max
相同,GetNextRandom
是一种使用System.Random
实例生成只需返回instance.Next(min, max)
的值即可获得随机整数。
使用yield的第一个代码段:
var list = new List<int>();
while(list.Count < numToGenerate)
{
var next = GetNextRandom(min, max);
if (!list.Contains(next))
{
list.Add(next);
yield return next;
}
}
使用正常回报的第二个片段:
var list = new List<int>();
while(list.Count < numToGenerate)
{
var next = GetNextRandom(min, max);
if (!list.Contains(next))
{
list.Add(next);
}
}
return list;
让我们假装这些片段是返回IEnumerable<int>
的方法的一部分。两者的主要区别是什么?我应该使用哪个以及为什么?我试图理解其中的功能差异。
答案 0 :(得分:1)
这取决于。您是否要消耗所有要求的值?如果没有,第一个有一些优势。例如,如果您在其上调用.Take(1)
,则您只进行了一次循环,并且只在列表中存储了一个值。
如果GetNextRandom
是一个非常缓慢的过程,并且您希望在生成UI时将值返回到UI,那么第一个在那里有优势。
但是如果你打算消费所有这些,如果来电者只是打电话给.ToList
以避免两次枚举,那么第二个可能更好,你可以调整你的回报键入IList
,以便调用者可以知道他们可以直接转到任何元素,并且可以对列表进行计数而无需再次枚举。 (另见Optimize LINQ for IList)
就垃圾收集而言,在第一个垃圾收集过程中,该方法完成后列表将可用于垃圾收集。在第二种情况下,调用者获取整个列表并且可以保持更长时间。
PS使用HashSet<T>
如果n很大,而不是在List