fub*_*ubo -1 c# foreach for-loop yield
我有一个产生返回值的方法.例如:
public static IEnumerable<int> GetValues()
{
for (int i = 0; i < 10; i++)
{
yield return i;
}
}
Run Code Online (Sandbox Code Playgroud)
当我用foreach调用这个方法时,yield return i;被调用了10次
foreach (int i in GetValues())
{
Console.WriteLine(i);
}
Run Code Online (Sandbox Code Playgroud)
当我用for循环调用它时,yield return i;被称为阶乘10次
for (int i = 0;i< 10;i++)
{
Console.WriteLine(GetValues().ElementAt(i));
}
Run Code Online (Sandbox Code Playgroud)
问题:有没有办法保持for-loop并避免那些多次调用ElementAt(i)?或者......我可以通过其索引从IEnumerable中调用一个元素,而不会导致其先前元素的迭代吗?我发现的唯一的事情就是这个,但是
for (int i = 0; i < 10; i++)
{
Console.WriteLine(GetValues().Skip(i).First());
}
Run Code Online (Sandbox Code Playgroud)
也不起作用.
如果要按索引访问项目并减少GetValues调用,则必须实现延迟枚举,这由GetValues以下内容生成:
var values = GetValues()
.ToArray();
for (int i = 0; i < values.Length; i++)
{
Console.WriteLine(values[i]);
}
Run Code Online (Sandbox Code Playgroud)
否则这个:
GetValues().Skip(i).First()
Run Code Online (Sandbox Code Playgroud)
将一次又一次地创建一个新的惰性枚举器.
你无法向后移动或引用IEnumerable <>对象中的随机索引 - 可以通过各种方式创建集合,包括随机性,并且没有神奇的方法来获取第n个元素而不迭代所有先前的元素.
常见的用法IEnumerable<>是:
foreach (var value in GetValues())
{
Console.WriteLine(value);
}
Run Code Online (Sandbox Code Playgroud)
这意味着:
using (var enumerator = GetValues().GetEnumerator())
{
while(enumerator.MoveNext())
{
var value = enumerator.Current;
Console.WriteLine(value);
}
}
Run Code Online (Sandbox Code Playgroud)
如果要引用特定索引,则需要有一个IList <>对象 - 您可以通过调用创建一个
.ToList()
将.ToArray()在另一响应提到实际上是一个稍微慢一点,并呼吁.ToList()将其制成阵列之前内部(因为数组需要有固定的大小,我们不知道在IEnumerable的元素个数,直到我们列举为末)
您可以创建自己的代理,lazy类,仅在需要时枚举枚举器
public static IEnumerable<int> GetValues()
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine("yielding " + i);
yield return i;
}
}
class LazyList<T>
{
IEnumerator<T> enumerator;
IList<T> list;
public LazyList(IEnumerable<T> enumerable)
{
enumerator = enumerable.GetEnumerator();
list = new List<T>();
}
public T this[int index]
{
get
{
while (list.Count <= index && enumerator.MoveNext())
{
list.Add(enumerator.Current);
}
return list[index];
}
}
}
static void Main(string[] args)
{
var lazy = new LazyList<int>(GetValues());
Console.WriteLine(lazy[0]);
Console.WriteLine(lazy[4]);
Console.WriteLine(lazy[2]);
Console.WriteLine(lazy[1]);
Console.WriteLine(lazy[7]);
Console.WriteLine(lazy[9]);
Console.WriteLine(lazy[6]);
Console.Read();
}
Run Code Online (Sandbox Code Playgroud)
将产生:
yielding 0
0
yielding 1
yielding 2
yielding 3
yielding 4
4
2
1
yielding 5
yielding 6
yielding 7
7
yielding 8
yielding 9
9
6
Run Code Online (Sandbox Code Playgroud)