Читать книги » Книги » Компьютеры и Интернет » Программирование » Язык программирования C#9 и платформа .NET5 - Эндрю Троелсен

Язык программирования C#9 и платформа .NET5 - Эндрю Троелсен

Читать книгу Язык программирования C#9 и платформа .NET5 - Эндрю Троелсен, Эндрю Троелсен . Жанр: Программирование.
Язык программирования C#9 и платформа .NET5 - Эндрю Троелсен
Название: Язык программирования C#9 и платформа .NET5
Дата добавления: 26 август 2023
Количество просмотров: 564
(18+) Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних просмотр данного контента СТРОГО ЗАПРЕЩЕН! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту для удаления материала.
Читать онлайн

Язык программирования C#9 и платформа .NET5 читать книгу онлайн

Язык программирования C#9 и платформа .NET5 - читать онлайн , автор Эндрю Троелсен

В 10-м издании книги описаны новейшие возможности языка C# 9 и .NET 5 вместе с подробным "закулисным" обсуждением, призванным расширить навыки критического мышления разработчиков, когда речь идет об их ремесле.
Книга охватывает ASP.NET Core, Entity Framework Core и многое другое наряду с последними обновлениями унифицированной платформы .NET, начиная с улучшений показателей производительности настольных приложений Windows в .NET 5 и обновления инструментария XAML и заканчивая расширенным рассмотрением файлов данных и способов обработки данных.
Все примеры кода были переписаны с учетом возможностей последнего выпуска C# 9.

Перейти на страницу:
Reset(), существует более легкий путь. Поскольку тип System.Array (а также многие другие классы коллекций) уже реализует интерфейсы IEnumerable и IEnumerator, вы можете просто делегировать запрос к System.Array следующим образом (обратите внимание, что в файл кода понадобится импортировать пространство имен System.Collections):

using System.Collections;

...

public class Garage : IEnumerable

{

  // System.Array уже реализует IEnumerator!

  private Car[] carArray = new Car[4];

  public Garage()

  {

    carArray[0] = new Car("FeeFee", 200);

    carArray[1] = new Car("Clunker", 90);

    carArray[2] = new Car("Zippy", 30);

    carArray[3] = new Car("Fred", 30);

  }

 // Возвратить IEnumerator объекта массива.

  public IEnumerator GetEnumerator()

    => carArray.GetEnumerator();

}

После такого изменения тип Garage можно безопасно использовать внутри конструкции foreach. Более того, учитывая, что метод GetEnumerator() был определен как открытый, пользователь объекта может также взаимодействовать с типом IEnumerator:

// Вручную работать с IEnumerator.

IEnumerator carEnumerator = carLot.GetEnumerator();

carEnumerator.MoveNext();

Car myCar = (Car)i.Current;

Console.WriteLine("{0} is going {1} MPH", myCar.PetName, myCar.CurrentSpeed);

Тем не менее, если вы предпочитаете скрыть функциональность IEnumerable на уровне объектов, то просто задействуйте явную реализацию интерфейса:

// Возвратить IEnumerator объекта массива.

IEnumerator IEnumerable.GetEnumerator()

  => return carArray.GetEnumerator();

В результате обычный пользователь объекта не обнаружит метод GetEnumerator() в классе Garage, в то время как конструкция foreach при необходимости будет получать интерфейс в фоновом режиме.

Построение итераторных методов с использованием ключевого слова yield

Существует альтернативный способ построения типов, которые работают с циклом foreach, предусматривающий использование итераторов. Попросту говоря, итератор — это член, который указывает, каким образом должны возвращаться внутренние элементы контейнера во время обработки в цикле foreach. В целях иллюстрации создайте новый проект консольного приложения по имени CustomEnumeratorWithYield и вставьте в него типы Car, Radio и Garage из предыдущего примера (снова переименовав пространство имен согласно текущему проекту). Затем модифицируйте тип Garage:

public class Garage : IEnumerable

{

  ...

  // Итераторный метод.

  public IEnumerator GetEnumerator()

  {

    foreach (Car c in carArray)

    {

      yield return c;

    }

  }

}

Обратите внимание, что показанная реализация метода GetEnumerator() осуществляет проход по элементам с применением внутренней логики foreach и возвращает каждый объект Car вызывающему коду, используя синтаксис yield return. Ключевое слово yield применяется для указания значения или значений, которые подлежат возвращению конструкцией foreach вызывающему коду. При достижении оператора yield return текущее местоположение в контейнере сохраняется и выполнение возобновляется с этого местоположения, когда итератор вызывается в следующий раз.

Итераторные методы не обязаны использовать ключевое слово foreach для возвращения своего содержимого. Итераторный метод допускается определять и так:

public IEnumerator GetEnumerator()

{

   yield return carArray[0];

   yield return carArray[1];

   yield return carArray[2];

   yield return carArray[3];

}

В этой реализации обратите внимание на то, что при каждом своем прохождении метод GetEnumerator() явно возвращает вызывающему коду новое значение. В рассматриваемом примере поступать подобным образом мало смысла, потому что если вы добавите дополнительные объекты к переменной-члену carArray, то метод GetEnumerator() станет рассогласованным. Тем не менее, такой синтаксис может быть полезен, когда вы хотите возвращать из метода локальные данные для обработки посредством foreach.

Защитные конструкции с использованием локальных функций (нововведение в версии 7.0)

До первого прохода по элементам (или доступа к любому элементу) никакой код в методе GetEnumerator() не выполняется. Таким образом, если до выполнения оператора yield возникает условие для исключения, то оно не будет сгенерировано при первом вызове метода, а лишь во время первого вызова MoveNext().

Чтобы проверить это, модифицируйте GetEnumerator():

public IEnumerator GetEnumerator()

{

  // Исключение не сгенерируется до тех пор, пока не будет вызван

  // метод MoveNext().

  throw new Exception("This won't get called");

  foreach (Car c in carArray)

  {

    yield return c;

  }

}

Если функция вызывается, как показано далее, и больше ничего не делается, тогда исключение никогда не сгенерируется:

using System.Collections;

...

Console.WriteLine("***** Fun with the Yield Keyword *****n");

Garage carLot = new Garage();

IEnumerator carEnumerator = carLot.GetEnumerator();

Console.ReadLine();

Код выполнится только после вызова MoveNext() и сгенерируется исключение. В зависимости от нужд программы это может быть как вполне нормально, так и нет. Ваш метод GetEnumerator() может иметь защитную конструкцию, которую необходимо выполнить при вызове метода в первый раз. В качестве примера предположим, что список формируется из базы данных. Вам может понадобиться организовать проверку, открыто ли подключение к базе данных, во время вызова метода, а не при проходе по списку. Или же может возникнуть потребность в проверке достоверности входных параметров метода Iterator(), который рассматривается далее.

Вспомните средство локальных функций версии C# 7, представленное в главе 4; локальные функции — это закрытые функции, которые определены внутри других функций. За счет перемещения yield return внутрь локальной функции, которая возвращается из главного тела метода, операторы верхнего уровня (до возвращения локальной функции) выполняются немедленно. Локальная функция выполняется при вызове MoveNext().

Приведите метод к следующему виду:

public IEnumerator GetEnumerator()

{

  // Это исключение сгенерируется немедленно

  throw new Exception("This will get called");

  return ActualImplementation();

  // Локальная функция и фактическая реализация IEnumerator

  IEnumerator ActualImplementation()

  {

    foreach (Car c in carArray)

    {

      yield return c;

    }

  }

}

Ниже показан тестовый код:

Console.WriteLine("***** Fun with the Yield Keyword *****n");

Garage carLot = new Garage();

try

{

  //

Перейти на страницу:
Комментарии (0)