Проблема с просмотром отладки в Visual Studio с методами перечисления yield return - PullRequest
11 голосов
/ 28 мая 2010

У меня есть метод, который возвращает IEnumerable<>, который он создает с использованием синтаксиса yield return:

namespace Validation
{
    public class UserValidator
    {
        public IEnumerable<ValidationError> Validate(User user)
        {
            if (String.IsNullOrEmpty(user.Name))
            {
                yield return new ValidationError("Name", ValidationErrorType.Required);
            }

            [...]

            yield break;
        }
    }
}

Если я добавлю точку останова в метод, я могу перешагнуть через каждую строку, но если я попытаюсь использовать окна Watch или Immediate для просмотра значения переменной, я получу эту ошибку:

Невозможно получить доступ к нестатическому члену внешний тип 'Validation.UserValidator.Validate' через вложенный тип 'Validation.UserValidator'

Кто-нибудь знает, почему это так и как я могу обойти это?

Ответы [ 3 ]

7 голосов
/ 28 мая 2010

ОК, только что попробовал, и я понимаю, что вы имеете в виду. Это больно! Я подозреваю, что это связано с закулисной работой, которую выполняет компилятор (создание вложенных классов и тому подобное) для реализации логики машинного состояния с возможностью восстановления состояния для yield. Один из способов обойти это (способ, которым я первоначально попробовал ваш код) - сделать метод Validate статичным, хотя, очевидно, это не очень хорошо для дизайна.

Я думаю, что причина, по которой сообщение об ошибке настолько тупое, заключается в некоторой комбинации:

  1. Сгенерированные классы не существуют в вашем источнике, поэтому у VS нет имен, по которым можно ссылаться на них.
  2. IIRC, имена, сгенерированные компилятором, содержат символы, недопустимые в идентификаторах C #, но допустимые в базовой системе типов Framework.

У меня сейчас нет Reflector под рукой, поэтому я не могу подтвердить, но если вы чувствуете себя как пятно легкого мазохизма, подумайте над своей сборкой и посмотрите на код, который пишет компилятор, чтобы позволить смертные используют хороший синтаксический сахар, такой как yield return :) В Интернете много информации о том, как именно все это работает.

Редактировать: после небольшого поиска, пара лучших:
http://blogs.msdn.com/b/ericlippert/archive/tags/iterators/
http://csharpindepth.com/Articles/Chapter6/IteratorBlockImplementation.aspx

5 голосов
/ 14 ноября 2011

Метод не запускается, пока вы не перечислите его.

var p = UserValidator.Validate(user).ToList();

Теперь вы можете отлаживать свой код.

3 голосов
/ 06 сентября 2011

У меня были похожие проблемы, и я сделал, чтобы изменить реализацию для создания списка элементов, а затем вернуть список.

Это позволило мне найти ошибку, исправить ее. После исправления ошибки я возвращаю реализацию к возврату доходности.

Болезненные.

...