使用IEnumerator迭代列表

gro*_*ine 12 .net c#

假设我有一个员工实例列表,employeeList

IEnumerator enumerator = employeeList.GetEnumerator();
            while (enumerator.MoveNext())
            {
                Console.Write(enumerator.Current + " ");
            }
Run Code Online (Sandbox Code Playgroud)

我有三个问题:

  1. 关于枚举器如何工作,我有一个很好的想法,就像C++中的迭代器一样.但是我不理解MoveNex方法(比如C++中的itr ++),因为它首先检查条件(是否在最后一个元素中),让我们说如果我们使用enumerator.Current来访问第一个元素,我认为它实际上当调用MoveNext()时,已经"移动"到列表中的下一个元素,因此当前指向的对象实际上是列表中的第二个元素?

  2. 我认为在使用enumerator.Current时我们可以访问当前元素是有意义的,例如,我们应该能够使用

    enumerator.Current.name

就像我们可以在C++中使用(*itr).name或itr => name一样,但C#看起来并没有实现这种功能,那么使用enumerator.Current有什么意义呢?

  1. 这个问题与IEnumerator无关.我刚看到一些像这样的代码:

IEnumerable<int> result = GetData() ?? Enumerable.Empty<int>;

作为C#的初学者,我只知道&&,||运营商,什么是" ??"?

Tim*_*ter 23

阅读文档:"在创建枚举数之后,枚举数位于集合中的第一个元素之前,第一个调用MoveNext 将枚举数提升到集合的第一个元素 "

代码的问题在于您将枚举数分配给非泛型枚举变量.这是有效的,因为通用IEnumerator<T>接口继承自非泛型.但这也是你不能使用Employee-class 属性的原因,因为类型是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;  // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

您还可以使用var哪个像C#中的实际类型的占位符一样工作:

using(var empEnumerator = employeeList.GetEnumerator())
{ ... }
Run Code Online (Sandbox Code Playgroud)

如果您只需要枚举整个集合,那就foreach更舒服了:

foreach(Employee emp in employeeList)
{
     Console.WriteLine(emp.Name);
}
Run Code Online (Sandbox Code Playgroud)


Hei*_*nzi 6

  1. 最初,枚举数位于第一个元素之前(因为枚举可能为空).因此,第一次调用MoveNext将其移动到第一个元素(如果枚举为空,则返回false).

  2. 您正在使用旧的非泛型版本IEnumerator,其中Current返回一个object.您可以将对象强制转换为具体类型并调用.name,或者更好地使用employeeList返回强类型IEnumerator<Employee>(例如List<Employee>)的类型.

  3. 这是空合并运算符.

PS:将来,请为每个问题创建一个SO问题.1 + 2可以看作是相关的,但3肯定不是.

PPS:如果您只想要一个以空格分隔的员工姓名列表,则根本不需要显式循环:

var names = String.Join(" ", employeeList.Select(e => e.name));
Run Code Online (Sandbox Code Playgroud)