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

У меня есть класс репозитория и класс служб, как показано ниже:

public class DinnerRepository
{
    DinnerDataContext db = new DinnerDataContext();

    public Dinner GetDinner(int id)
    {
        return db.Dinners.SingleOrDefault(d => d.DinnerID == id);   
    }

// Others Code        
}



public class Service
{
        DinnerRepository repo = new DinnerRepository(); 
        Dinner dinner = repo.GetDinner(5);

// Other Code
}

Это вызывает ошибку:

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

Несмотря на то, что я включил класс DinnerRepository, выставляем его метод GetDinner() в классе обслуживания. Это отлично работает с кодом ниже. Есть ли альтернатива этому, или это стандартная практика? Я не могу использовать статические методы здесь.

public class Service
{

    public Service()
    {
        DinnerRepository repo = new DinnerRepository(); 
        Dinner dinner = repo.GetDinner(5);
    }

}

Ответы

Ответ 1

Лично я просто инициализирую поля в конструкторе:

public class Service
{
    private readonly DinnerRepository repo;
    private readonly Dinner dinner;

    public Service()
    {
        repo = new DinnerRepository();
        dinner = repo.GetDinner(5);
    }
}

Обратите внимание, что это не то же самое, что код, который вы показываете в нижней части вопроса, поскольку это только объявление локальных переменных. Если вам нужны только локальные переменные, это хорошо, но если вам нужны переменные экземпляра, используйте код, как указано выше.

В принципе, инициализаторы полей ограничены тем, что они могут сделать. Из раздела 10.5.5.2 спецификации С# 4:

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

( "Таким образом" и "поэтому" выглядит неправильно для меня - это незаконно ссылаться на элемент через простое имя, потому что оно ссылается на this - я буду пинговать Mads об этом, но это в основном соответствующий раздел.)

Ответ 2

Даже если выражения инициализации гарантированы в "textual order" , это незаконно для инициализаторов полей экземпляра для доступа к this ссылке, и вы неявно используете его в

Dinner dinner = repo.GetDinner(5); 

что эквивалентно

Dinner dinner = this.repo.GetDinner(5);

Лучшей практикой IMHO является резервирование инициализации поля до постоянных значений или простой инструкции new. Что-нибудь более волосатое, чем это должно идти к конструктору.