Yurijnd.com
Четверг, 06.02.2025, 21:22
Меню сайта

Вход на сайт

Поиск

Друзья сайта
  • Официальный блог
  • Сообщество uCoz
  • FAQ по системе
  • Инструкции для uCoz

  • Статистика

    Онлайн всего: 2
    Гостей: 2
    Пользователей: 0

    Итераторы (C# и Visual Basic)

    Visual Studio 2013
     

    Итератор можно использовать для прохода по коллекции, такой как список и массив.

    Метод итератора или метод доступа get выполняет настраиваемый проход по коллекции. Метод итератора использует операторYield (Visual Basic) или yield return (C#) для поочередного возврата каждого элемента. При достижении оператора Yield или yield return текущее расположение в коде запоминается. При следующем вызове функции итератора выполнение возобновляется с того места.

    Используется итератор из клиентского кода с помощью выписки For Each… Next (Visual Basic) или foreach (C-#) или с помощью запроса LINQ.

    В следующем примере, первая итерация цикла For Each или foreach приведёт к вызову метода итератора SomeNumbers пока не достигнет выражения Yield или yield return. Эта итерация возвращает значение 3, и сохраняется текущее расположение в методе итератора. На следующей итерации цикла, выполнение метода итератора возобновляется, и снова приостанавливается при достижении оператора Yield или yield return. Эта итерация возвращает значение 5, а текущее расположение в методе итератора снова сохраняются. Цикл завершается при достижении конца метода итератора.

     
    static void Main()
    {
     foreach (int number in SomeNumbers())
     {
     Console.Write(number.ToString() + " ");
     }
     // Output: 3 5 8
     Console.ReadKey();
    }
    
    public static System.Collections.IEnumerable SomeNumbers()
    {
     yield return 3;
     yield return 5;
     yield return 8;
    }
    

    Тип возвращаемого значения метода итератора или метода доступа get может быть IEnumerableIEnumerableIEnumerator илиIEnumerator.

    Можно использовать оператор C# Exit Function или Return (Visual Basic) или оператор yield break, чтобы завершить итерацию.

    Функция итератора Visual Basic или объявление метода доступа get включает в себя модификатор Iterator.

    Итераторы были введены в C# в Visual Studio 2005 и появились в Visual Basic в Visual Studio 2012.

    Содержание раздела

    Простой итератор

     

    В следующем примере имеется оператор Yield или yield return, который находится внутри цикла For… Next (Visual Basic) или For(C#). В Main каждая итерация оператора For Each или foreach создает вызов функции итератора, которая выполняет следующий оператор Yield или yield return.

     
    static void Main()
    {
     foreach (int number in EvenSequence(5, 18))
     {
     Console.Write(number.ToString() + " ");
     }
     // Output: 6 8 10 12 14 16 18
     Console.ReadKey();
    }
    
    public static System.Collections.Generic.IEnumerable<int>
     EvenSequence(int firstNumber, int lastNumber)
    {
     // Yield even numbers in the range. 
     for (int number = firstNumber; number <= lastNumber; number++)
     {
     if (number % 2 == 0)
     {
     yield return number;
     }
     }
    }
    

    Создание класса коллекции

     
    Примечание Примечание

    Для остальных примеров в этом разделе добавьте операторы Imports (Visual Basic) или директивы C# using для пространств имен System.Collections и System.Collections.Generic.

    В следующем примере класс DaysOfTheWeek реализует интерфейс IEnumerable, который требует метода GetEnumerator.Компилятор неявно вызывает метод GetEnumerator, который возвращает IEnumerator.

    Метод GetEnumerator возвращает каждую строку поочередно с помощью оператора Yield или yield return. В коде Visual Basic, модификатор Iterator находится в объявлении функции.

     
    static void Main()
    {
     DaysOfTheWeek days = new DaysOfTheWeek();
    
     foreach (string day in days)
     {
     Console.Write(day + " ");
     }
     // Output: Sun Mon Tue Wed Thu Fri Sat
     Console.ReadKey();
    }
    
    public class DaysOfTheWeek : IEnumerable
    {
     private string[] days = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
    
     public IEnumerator GetEnumerator()
     {
     for (int index = 0; index < days.Length; index++)
     {
     // Yield each day of the week. 
     yield return days[index];
     }
     }
    }
    

    В следующем примере создается класс Zoo, содержащий коллекцию животных.

    Оператор For Each или foreach, который обращается к экземпляру класса (theZoo), неявно вызывает метод GetEnumerator.Операторы For Each или foreach, которые обращаются к свойствам Birds и Mammals, используют метод итератора с именемAnimalsForType.

     
    static void Main()
    {
     Zoo theZoo = new Zoo();
    
     theZoo.AddMammal("Whale");
     theZoo.AddMammal("Rhinoceros");
     theZoo.AddBird("Penguin");
     theZoo.AddBird("Warbler");
    
     foreach (string name in theZoo)
     {
     Console.Write(name + " ");
     }
     Console.WriteLine();
     // Output: Whale Rhinoceros Penguin Warbler 
    
     foreach (string name in theZoo.Birds)
     {
     Console.Write(name + " ");
     }
     Console.WriteLine();
     // Output: Penguin Warbler 
    
     foreach (string name in theZoo.Mammals)
     {
     Console.Write(name + " ");
     }
     Console.WriteLine();
     // Output: Whale Rhinoceros
    
     Console.ReadKey();
    }
    
    public class Zoo : IEnumerable
    {
     // Private members. 
     private List<Animal> animals = new List<Animal>();
    
     // Public methods. 
     public void AddMammal(string name)
     {
     animals.Add(new Animal { Name = name, Type = Animal.TypeEnum.Mammal });
     }
    
     public void AddBird(string name)
     {
     animals.Add(new Animal { Name = name, Type = Animal.TypeEnum.Bird });
     }
    
     public IEnumerator GetEnumerator()
     {
     foreach (Animal theAnimal in animals)
     {
     yield return theAnimal.Name;
     }
     }
    
     // Public members. 
     public IEnumerable Mammals
     {
     get { return AnimalsForType(Animal.TypeEnum.Mammal); }
     }
    
     public IEnumerable Birds
     {
     get { return AnimalsForType(Animal.TypeEnum.Bird); }
     }
    
     // Private methods. 
     private IEnumerable AnimalsForType(Animal.TypeEnum type)
     {
     foreach (Animal theAnimal in animals)
     {
     if (theAnimal.Type == type)
     {
     yield return theAnimal.Name;
     }
     }
     }
    
     // Private class. 
     private class Animal
     {
     public enum TypeEnum { Bird, Mammal }
    
     public string Name { get; set; }
     public TypeEnum Type { get; set; }
     }
    }
    

    Блоки "Try" в Visual Basic

     

    Visual Basic допускает оператор Yield в блоке TryОператор Try... Catch... Finally (Visual Basic). Блок Try, имеющий оператор Yield, может содержать блоки Catch и блок Finally.

    Примечание C# Примечание C#

    C# допускает оператор yield return в блоке try оператора try-finally. Блок try, имеющий оператор yield return, не может иметь блоков catch.

    В следующем примере Visual Basic в функции итератора содержится блок TryCatch и Finally. Блок Finally в функции итератора выполняется перед завершением итерации For Each.

     
    Sub Main()
     For Each number As Integer In Test()
     Console.WriteLine(number)
     Next
     Console.WriteLine("For Each is done.")
    
     ' Output: 
     ' 3 
     ' 4 
     ' Something happened. Yields are done. 
     ' Finally is called. 
     ' For Each is done.
     Console.ReadKey()
    End Sub 
    
    Private Iterator Function Test() As IEnumerable(Of Integer)
     Try
     Yield 3
     Yield 4
     Throw New Exception("Something happened. Yields are done.")
     Yield 5
     Yield 6
     Catch ex As Exception
     Console.WriteLine(ex.Message)
     Finally
     Console.WriteLine("Finally is called.")
     End Try 
    End Function
    

    Оператор Yield не может быть внутри блока Catch или блока Finally.

    Если содержимое в For Each (вместо метода итератора) вызывает исключение, то блок Catch в функции итератора не выполняется, но выполняется блок Finally в функции итератора. Блок Catch внутри функции итератора перехватывает только исключения, происходящие внутри функции итератора.

    Следующая страница

    Copyright MyCorp © 2025
    Сделать бесплатный сайт с uCoz