C# 由IEnumerable生成的消费序列
我想使用C# 由IEnumerable生成的消费序列,c#,yield-return,C#,Yield Return,我想使用IEnumerable生成一个值序列——具体来说,是一个类似Excel的列标题列表 private IEnumerable<string> EnumerateSymbolNames() { foreach (var sym in _symbols) { yield return sym; } foreach (var sym1 in _symbols) { foreach (var sym2 in _symbols) {
IEnumerable
生成一个值序列——具体来说,是一个类似Excel的列标题列表
private IEnumerable<string> EnumerateSymbolNames()
{
foreach (var sym in _symbols)
{
yield return sym;
}
foreach (var sym1 in _symbols)
{
foreach (var sym2 in _symbols)
{
yield return sym1 + sym2;
}
}
yield break;
}
private readonly string[] _symbols = new string[] { "A", "B", "C", ...};
。。。但这些都不起作用。(所有重复返回“A”。)
根据对的回复,我想知道我想要什么甚至是可能的——尽管对那篇文章的一些回复建议使用与我上一篇类似的技巧
不,这不是家庭作业:)当您使用
GetEnumerator
时,每次迭代都需要使用相同的枚举器。如果第二次调用GetEnumerator,它将在集合的开头重新开始
如果要使用
Take
,必须首先跳过已处理的记录数。使用GetEnumerator
时,每次迭代都需要使用相同的枚举器。如果第二次调用GetEnumerator,它将在集合的开头重新开始
如果要使用
Take
,必须首先跳过已处理的记录数。此代码对我有效
var states = EnumerateSymbolNames();
var stateMachine = states.GetEnumerator();
do
{
//something
} while (stateMachine.MoveNext());
在该循环中打印结果时,它成功地生成以下输出:
A
B
C
...
AA
AB
AC
...
BA
BB
...
这正是我认为你想要的…这段代码对我有用
var states = EnumerateSymbolNames();
var stateMachine = states.GetEnumerator();
do
{
//something
} while (stateMachine.MoveNext());
在该循环中打印结果时,它成功地生成以下输出:
A
B
C
...
AA
AB
AC
...
BA
BB
...
这正是我认为您想要的…正如@cadrell0的回答和@Mr Steak的评论所指出的,我需要做的是保留对
EnumerateSymbolNames().GetEnumerator()返回的枚举器的引用
当您在foreach
循环中时,这是为您隐式完成的:迭代器变量包装一个枚举器,它(我假设)的作用域是循环的局部。所以——这是关键——当迭代器块执行时(相当于)
。。。您总是使用相同的枚举数。而我所做的是每次创建/获取一个不同的(新)枚举器。可以预见的是,它总是从序列的第一个位置开始。这可能对每个人都很明显,但我除外;事后看来,这对我来说也是显而易见的。(我认为枚举数是序列的一种单例属性,假设每次都返回相同的枚举数。)
以下是我想要的:
public class SymbolGenerator
{
private readonly string[] _symbols = { "A", "B", "C", ... };
private readonly IEnumerator<string> _enumerator;
public SymbolGenerator()
{
_enumerator = EnumerateSymbols().GetEnumerator();
}
public string GetNextSymbol()
{
_enumerator.MoveNext();
return _enumerator.Current;
}
private IEnumerable<string> EnumerateSymbols()
{
// (unchanged)
}
}
公共类符号生成器
{
私有只读字符串[]_符号={“A”、“B”、“C”、…};
私有只读IEnumerator\u枚举器;
公共符号生成器()
{
_枚举器=枚举符号().GetEnumerator();
}
公共字符串GetNextSymbol()
{
_枚举数。MoveNext();
返回_enumerator.Current;
}
私有IEnumerable枚举符号()
{
//(不变)
}
}
正如@cadrell0的回答和@Mr Steak的评论所指出的,我需要做的是保留对EnumerateSymbolNames().GetEnumerator()返回的枚举数的引用。
当您在foreach
循环中时,这是为您隐式完成的:迭代器变量包装一个枚举器,它(我假设)的作用域是循环的局部。所以——这是关键——当迭代器块执行时(相当于)
。。。您总是使用相同的枚举数。而我所做的是每次创建/获取一个不同的(新)枚举器。可以预见的是,它总是从序列的第一个位置开始。这可能对每个人都很明显,但我除外;事后看来,这对我来说也是显而易见的。(我认为枚举数是序列的一种单例属性,假设每次都返回相同的枚举数。)
以下是我想要的:
public class SymbolGenerator
{
private readonly string[] _symbols = { "A", "B", "C", ... };
private readonly IEnumerator<string> _enumerator;
public SymbolGenerator()
{
_enumerator = EnumerateSymbols().GetEnumerator();
}
public string GetNextSymbol()
{
_enumerator.MoveNext();
return _enumerator.Current;
}
private IEnumerable<string> EnumerateSymbols()
{
// (unchanged)
}
}
公共类符号生成器
{
私有只读字符串[]_符号={“A”、“B”、“C”、…};
私有只读IEnumerator\u枚举器;
公共符号生成器()
{
_枚举器=枚举符号().GetEnumerator();
}
公共字符串GetNextSymbol()
{
_枚举数。MoveNext();
返回_enumerator.Current;
}
私有IEnumerable枚举符号()
{
//(不变)
}
}
在上一个示例中,只需将枚举器
设置为字段并初始化一次,而不是每次调用EnumerateSymbolNames().GetEnumerator()
即可。在上一个示例中,只需将枚举器
设置为字段并初始化一次,而不是调用EnumerateSymbolNames().GetEnumerator()
每次。不是为了反驳这个答案中的任何内容,而是为了补充一点,枚举器就是问题中提到的状态机。enumerable在初始状态下生成该状态机的一个新实例。不反驳此答案中的任何内容,但要补充一点,枚举器就是问题中提到的状态机。可枚举项在初始状态下生成该状态机的新实例。