假设我有一个员工实例列表,employeeList
IEnumerator enumerator = employeeList.GetEnumerator();
while (enumerator.MoveNext())
{
Console.Write(enumerator.Current + " ");
}
我有三个问题:
我对枚举器的工作方式有一个很好的想法,就像C ++中的迭代器一样。 但是我不理解MoveNex方法(比如C ++中的itr ++),因为它首先检查条件(是否在最后一个元素中),让我们说如果我们使用enumerator.Current来访问第一个元素,我认为它实际上当调用MoveNext()时,已经“移动”到列表中的下一个元素,因此当前指向的对象实际上是列表中的第二个元素吗?
我认为在使用enumerator.Current时我们可以访问当前元素是有意义的,例如,我们应该可以使用
enumerator.Current.name
就像我们可以在C ++中使用(* itr).name或itr =>名称一样,但C#看起来并没有实现这种功能,那么使用enumerator.Current是什么意思?
IEnumerable<int> result = GetData() ?? Enumerable.Empty<int>;
作为C#的初学者,我只知道&&
,||
运算符,什么是“??
”?
答案 0 :(得分:20)
阅读documentation:&#34;创建枚举数后,枚举数位于集合中第一个元素之前的,并且第一次调用{{1 将枚举数推进到集合的第一个元素&#34;
代码的问题在于您将枚举数分配给非泛型枚举器变量。这是有效的,因为通用MoveNext
接口继承自非泛型。但这也是您无法使用IEnumerator<T>
类属性的原因,因为类型为Employee
。您必须先将Object
转换为正确的类型。
因此,最好使用通用版本(并使用enumerator.Current
正确使用它):
using
你也可以使用using(IEnumerator<Employee> empEnumerator = employeeList.GetEnumerator())
{
while(empEnumerator.MoveNext())
{
// now empEnumerator.Current is the Employee instance without casting
Employee emp = empEnumerator.Current;
string empName = emp.Name; // ...
}
}
,就像C#中真实类型的占位符一样:
var
如果您只需要枚举整个集合,using(var empEnumerator = employeeList.GetEnumerator())
{ ... }
会更舒服:
foreach
答案 1 :(得分:6)
最初,枚举器位于之前第一个元素(因为枚举可能为空)。因此,第一次调用MoveNext
会将其移动到第一个元素(如果枚举为空,则返回false)。
您使用的是IEnumerator
旧的非通用版本,其中Current
返回object
。您可以将对象强制转换为具体类型并调用.name
,或者更好的是,使用employeeList
类型返回强类型IEnumerator<Employee>
(例如List<Employee>
)
PS:将来,请为每个问题创建一个SO问题。 1 + 2可以看作是相关的,但3肯定不是。
PPS:如果您只想要一个以空格分隔的员工姓名列表,那么您根本不需要显式循环:
var names = String.Join(" ", employeeList.Select(e => e.name));
答案 2 :(得分:3)
以这种方式使用IEnumerable
:
foreach (var e in employeeList)
{
Console.Write(e + " ");
}
答案 3 :(得分:-1)
公开一个枚举器,它支持对非泛型集合的简单迭代。
FEED_EXPORT_ENCODING = 'utf-8'
foreach (var employee in employeeList)
{
// do your stuff here, you have full employee object
Console.WriteLine(employee.FirstName);
}
运算符称为null-coalescing运算符。如果操作数不为null,则返回左侧操作数;否则它会返回右手操作数。