Поделиться через


Практическое руководство. Доступ к классу коллекции с помощью оператора foreach (Руководство по программированию в C#)

Обновлен: Ноябрь 2007

В следующем примере показана запись неуниверсального класса коллекции, который можно использовать с оператором foreach. Класс является средством разметки строки, подобно функции библиотеки времени выполнения C strtok_s.

9yb8xew9.alert_note(ru-ru,VS.90).gifПримечание.

Этот пример представляет рекомендованный способ, только если использование универсального класса коллекции невозможно. Универсальные шаблоны поддерживаются языком C# и платформой .NET Framework версии 2.0 или более поздней. Пример реализации строго типизированного универсального класса коллекции, который поддерживает IEnumerable<T> и тем самым предупреждает возникновение проблем, описываемых далее в документе, см. в разделе Практическое руководство. Создание блока итератора для общего списка (руководство по программированию в C#).

В следующем примере Tokens разбивает предложение "This is a sample sentence." на маркеры, используя в качестве разделителей ' ' и '-', и перечисляет эти маркеры с помощью оператора foreach.

Tokens f = new Tokens("This is a sample sentence.", new char[] {' ','-'});

foreach (string item in f)
{
    System.Console.WriteLine(item);
}

Внутренне Tokens использует массив, который реализует IEnumerator и сам IEnumerable. В этом примере методы перечисления массива могли бы использоваться кодом как собственные, однако это изменило бы цель примера.

В C# отсутствует крайняя необходимость наследования класса коллекции от IEnumerable и IEnumerator для обеспечения совместимости с foreach. Пока для класса имеются необходимые члены GetEnumerator, MoveNext, Reset и Current, он будет работать с оператором foreach. Пропуск интерфейсов позволяет определять возвращаемый тип Current более точно, чем Object, обеспечивающий строгую типизацию.

Например, в примере кода, приведенном ранее в этом разделе, измените следующие строки.

// No longer inherits from IEnumerable:
public class Tokens  
// Doesn't return an IEnumerator:
public TokenEnumerator GetEnumerator()  
// No longer inherits from IEnumerator:
public class TokenEnumerator  
// Type-safe: returns string, not object:
public string Current  

Теперь, поскольку Current возвращает строку, компилятор может обнаружить использование в операторе foreach несовместимого типа.

// Error: cannot convert string to int:
foreach (int item in f)  

Недостатком пропуска IEnumerable и IEnumerator является отсутствие взаимодействия класса коллекции с операторами foreach или их эквивалентами в других языках, совместимых со средой CLR.

Самые подходящие возможности — строгую типизацию в C# и взаимодействие с другими языками, совместимыми с CLR — можно выбрать путем наследования от IEnumerable и IEnumerator и явной реализации интерфейса, как показано в следующем примере.

Пример

using System.Collections;

// Declare the Tokens class:
public class Tokens : IEnumerable
{
    private string[] elements;

    Tokens(string source, char[] delimiters)
    {
        // Parse the string into tokens:
        elements = source.Split(delimiters);
    }

    // IEnumerable Interface Implementation:
    //   Declaration of the GetEnumerator() method 
    //   required by IEnumerable
    public IEnumerator GetEnumerator()
    {
        return new TokenEnumerator(this);
    }


    // Inner class implements IEnumerator interface:
    private class TokenEnumerator : IEnumerator
    {
        private int position = -1;
        private Tokens t;

        public TokenEnumerator(Tokens t)
        {
            this.t = t;
        }

        // Declare the MoveNext method required by IEnumerator:
        public bool MoveNext()
        {
            if (position < t.elements.Length - 1)
            {
                position++;
                return true;
            }
            else
            {
                return false;
            }
        }

        // Declare the Reset method required by IEnumerator:
        public void Reset()
        {
            position = -1;
        }

        // Declare the Current property required by IEnumerator:
        public object Current
        {
            get
            {
                return t.elements[position];
            }
        }
    }


    // Test Tokens, TokenEnumerator
    static void Main()
    {
        // Testing Tokens by breaking the string into tokens:
        Tokens f = new Tokens("This is a sample sentence.", new char[] {' ','-'});

        foreach (string item in f)
        {
            System.Console.WriteLine(item);
        }
    }
}
/* Output:
    This
    is
    a
    sample
    sentence.  
*/

См. также

Основные понятия

Руководство по программированию в C#

Ссылки

Массивы (Руководство по программированию на C#)

Классы коллекций (руководство по программированию в C#)

System.Collections.Generic

Другие ресурсы

Справочник по C#