2017-01-04 2 views
3

Пусть у меня есть список экземпляров сотрудника, employeeListс помощью IEnumerator для перебора списка

IEnumerator enumerator = employeeList.GetEnumerator(); 
      while (enumerator.MoveNext()) 
      { 
       Console.Write(enumerator.Current + " "); 
      } 

У меня есть три вопроса:

  1. У меня есть роды представление о том, как работает переписчик, как итератор в C++. Но я не понимаю метод MoveNex (например, itr ++ в C++), потому что он сначала проверяет условие (будь то в последнем элементе), скажем, если мы используем enumerator.Current для доступа к первому элементу, я думаю, что это на самом деле уже «переместился» на следующий элемент в списке, когда был вызван MoveNext(), поэтому объект, который Current points является фактически вторым элементом в списке?

  2. Я думаю, что это будет иметь смысл, что мы можем получить доступ к текущему элементу при использовании enumerator.Current, например, мы должны быть в состоянии использовать

    enumerator.Current.name

так же, как мы можем use (* itr) .name или itr => name в C++, но C# выглядит как не реализующий этот вид функции, тогда в чем смысл использовать enumerator.Current?

  1. Этот вопрос не связан с IEnumerator. Я только что видел некоторый код, как это:

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

Как новичок в C#, я знаю только &&, || операторов, что "??"?

+2

3 является оператором с нулевым коалесцированием: https://msdn.microsoft.com/en-us/library/ms173224%28v=vs.100%29.aspx –

+0

Почему вы не используете 'foreach'? Почему вы пытаетесь использовать базовую реализацию? –

+0

Замечание, если вы получаете объект 'IEnumerator' вручную (а не через' foreach'), вам нужно его утилизировать, когда вы закончите перечисление, как правило, путем обертывания всего элемента в блок 'using' , 'using (IEnumerator enumerator = ...) {while (...) {}}' –

ответ

9

Read documentation: «После того, как переписчик создаются, перечислитель позиционируется перед первым элемента в коллекции, и первый вызов MoveNextпродвигает перечислитель к первому элементу коллекции»

проблема с вашим кодом заключается в том, что вы назначаете перечислитель переменной, не являющейся общим перечислителем. Это работает, потому что общий интерфейс IEnumerator<T> наследует от не-generic. Но это также причина, по которой вы не можете использовать свойства класса Employee, так как тип Object. Сначала вы должны набрать enumerator.Current.

Поэтому лучше использовать общую версию (и dipose его правильно с 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; // ... 
    } 
} 

Вы можете также использовать var, который работает как заполнитель для вещественного типа в C#:

using(var empEnumerator = employeeList.GetEnumerator()) 
{ ... } 

Если вам нужно всего перечислить всю коллекцию, то foreach удобнее:

foreach(Employee emp in employeeList) 
{ 
    Console.WriteLine(emp.Name); 
} 
3

Используйте IEnumerable только так:

foreach (var e in employeeList) 
{ 
    Console.Write(e + " "); 
} 
6
  1. Изначально перечислитель позиционируется перед тем первый элемент (так как перечислимы может быть пустым). Таким образом, первый вызов перемещает его в первый элемент (или возвращает false, если перечислимый пуст).

  2. Вы используете старую, не общую версию IEnumerator, где Current возвращает object. Вы можете наложить объект на конкретный тип и вызвать .name, или, что еще лучше, использовать тип для employeeList, который возвращает строго типизированный IEnumerator<Employee> (такой как List<Employee>).

  3. Это null-coalescing operator.

PS: В будущем, пожалуйста, создайте один вопрос на вопрос. 1 + 2 можно рассматривать как связанные, но 3 определенно нет.

PPS: Если вы просто хотите, разделенных пробела списка имен сотрудников, вам не нужна явная петля на все:

var names = String.Join(" ", employeeList.Select(e => e.name)); 
-1

IEnumerable Interface

разоблачает перечислитель, который поддерживает простую итерацию над необщей коллекцией.

foreach (var employee in employeeList) 
{ 
    // do your stuff here, you have full employee object 
    Console.WriteLine(employee.FirstName); 
} 

c# null coalescing operator

?? Оператор называется оператором нуль-коалесцирующий. Он возвращает левый операнд, если операнд не равен нулю; в противном случае он возвращает правый операнд.

+0

-1, опять же, для того, чтобы не использовать кавычки, чтобы указать, какой контент скопирован из вашего источника. –