Интересное использование C# приводит к ключевому слову в учебном руководстве по Ужину Компьютерного фаната

Работая через учебное руководство (Профессионал ASP.NET MVC - Ужин Компьютерного фаната), я столкнулся с этим отрывком кода:

public IEnumerable<RuleViolation> GetRuleViolations() {
    if (String.IsNullOrEmpty(Title))
        yield return new RuleViolation("Title required", "Title");
    if (String.IsNullOrEmpty(Description))
        yield return new RuleViolation("Description required","Description");
    if (String.IsNullOrEmpty(HostedBy))
        yield return new RuleViolation("HostedBy required", "HostedBy");
    if (String.IsNullOrEmpty(Address))
        yield return new RuleViolation("Address required", "Address");
    if (String.IsNullOrEmpty(Country))
        yield return new RuleViolation("Country required", "Country");
    if (String.IsNullOrEmpty(ContactPhone))
        yield return new RuleViolation("Phone# required", "ContactPhone");
    if (!PhoneValidator.IsValidNumber(ContactPhone, Country))
        yield return new RuleViolation("Phone# does not match country", "ContactPhone");
    yield break;
}

Я читал на yield, но я предполагаю, что мое понимание является все еще немного туманным. То, что это, кажется, делает, создают объект, который позволяет циклически повторяться через объекты в наборе, на самом деле не делая циклического повторения, только после того как это абсолютно необходимо.

Этот пример является немного странным для меня, все же. То, что я думаю, что это делает, задерживает создание любого RuleViolation экземпляры, пока программист на самом деле не запрашивает определенного объекта в наборе с помощью также for each или дополнительный метод LINQ как .ElementAt(2).

Вне этого, тем не менее, у меня есть некоторые вопросы:

  1. Когда делают условные части if операторы оценены? Когда GetRuleViolations() назван или когда счетное на самом деле выполнено с помощью итераций? Другими словами, если значение Title изменения от null к Really Geeky Dinner между временем, когда я звоню GetRuleViolations() и время, которого я пытаюсь на самом деле выполнить итерации по нему, будет RuleViolation("Title required", "Title") быть созданными или нет?

  2. Почему yield break; необходимый? Что это действительно делает здесь?

  3. Скажем, Title является пустым или пустым. Если я звоню GetRuleViolations() тогда выполните итерации за получающиеся счетные два раза подряд, сколько раз будет new RuleViolation("Title required", "Title") позвониться?

13
задан devuxer 28 December 2009 в 19:40
поделиться

3 ответа

Функция, которая содержит команды выхода , обрабатывается иначе, чем обычная функция. То, что происходит за кулисами при вызове этой функции, это то, что анонимный тип построен из специфического IEnumerable типа функции, функция создает объект этого типа и возвращает его. Класс анонимности содержит логику, которая выполняет тело функции до следующей команды yield каждый раз при вызове IEnumerable.MoveNext. Это немного вводит в заблуждение, тело функции выполняется не одной партией, как обычная функция, а фигурами, каждая фигура выполняется, когда перечислитель движется на шаг вперед.

Что касается ваших вопросов:

  1. Как я уже говорил, каждая если выполняется при итерации к следующему элементу.
  2. break действительно не нужен в приведенном выше примере. Он завершает перечисление.
  3. Каждый раз, когда вы выполняете итерацию над перечислением, вы заставляете код выполняться заново. Поставьте точку останова на соответствующую строку и проверьте сами.
17
ответ дан 1 December 2019 в 21:38
поделиться

1) Возьмем этот более простой пример:

public void Enumerate()
{
    foreach (var item in EnumerateItems())
    {
        Console.WriteLine(item);
    }
}

public IEnumerable<string> EnumerateItems()
{
    yield return "item1";
    yield return "item2";
    yield break;
}

Каждый раз при вызове MoveNext() из IEnumerator код возвращается из точки yield и переходит в следующую исполняемую строку кода.

2) перерыв в доходности; скажет IEnumerator, что больше нечего перечислять.

3) один раз за перечисление.

Используя перерыв;

public IEnumerable<string> EnumerateUntilEmpty()
{
    foreach (var name in nameList)
    {
        if (String.IsNullOrEmpty(name)) yield break;
        yield return name;
    }     
}
6
ответ дан 1 December 2019 в 21:38
поделиться

Краткий вариант:

1: урожайность - это магическое ключевое слово "Остановить и вернуться позже", поэтому если высказывания перед "активным" были оценены.

2: перерыв урожайности явно завершает перечисление (думайте "перерыв" в случае переключения)

3: каждый раз. Конечно же, можно кэшировать результат, например, превратив его в список, а затем выполнить итерацию над ним

.
2
ответ дан 1 December 2019 в 21:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: