Возможный дубликат:
Почему Don & rsquo; t С# Разрешить статические методы для реализации интерфейса?
В моем приложении я хочу использовать репозиторий, который будет выполнять доступ к необработанным данным (TestRepository, SqlRepository, FlatFileRepository и т.д.).
Поскольку такой репозиторий будет использоваться во время выполнения моего приложения, мне показалось разумным сделать его статическим классом, чтобы я мог пойти
SqlRepository.GetTheThingById(5);
без необходимости регенерации все время.
Поскольку я хочу, чтобы мои репозитории были взаимозаменяемыми, я хочу, чтобы они реализовали общий интерфейс: IRepository.
Но когда я пытаюсь сделать это, я получаю
"Static classes cannot implement interfaces"
Почему они не могут?
Как вы предлагаете мне изменить свой дизайн? Можно ли использовать шаблон?
UPDATE
Пять лет спустя: этот вопрос посещается 20k + раз, я узнал о недостатках шаблона репозитория, узнал о IoC и понял, что мой вопрос был плохо сформулирован.
Я действительно не спрашивал, что такое спецификация интерфейса С#, а почему именно намеренно ограничивает меня именно этим способом.
Практический ответ заключается в том, что синтаксис вызова метода в экземпляре или в типе отличается. Но вопрос закрыт.
Ответ 1
Интерфейсы не могут иметь статические методы. Класс, реализующий интерфейс, должен реализовать их как методы экземпляра. Статические классы не могут иметь методы экземпляра. Что и требовалось доказать.
Ответ 2
Возможно, наш опыт поможет. Вместо SqlRepository в качестве статического класса мы используем AutoFac для инъекций и скрываем контейнер за статическим классом. Затем каждый объект имеет свойство статического хранилища:
public class Part : inheritence...
{
public static IPartRepository Repository
{
get { return IoCContainer.GetInstance<IRepository<Part>>(); }
}
// ... more part-y stuff
}
Таким образом, мы можем поменять реализацию, и вызывающие абоненты всегда знают, где ее получить:
Part p = Part.Repository.Get(id);
В другом проекте есть PartRepository, зарегистрированный в контейнере:
public class PartRepository : IPartRepository
{
// IPartRepository implementation that talks to injected DAL
}
В еще одном проекте у нас есть mocks для тестирования, в том числе репозитории, предварительно загруженные известными:
public class MockPartRepository : Dictionary<Part, int>, IPartRepository
{
// IPartRepository implementation based on dictionary
}
... и он зарегистрирован в контейнере для модульного тестирования. SAME-вызов получает репозиторий:
Part p = Part.Repository.Get(id);
Ответ 3
По определению интерфейсы создают контракт для выполнения экземпляров. Поскольку вы не можете создавать статический класс, статические классы не могут реализовывать интерфейсы.
Нет необходимости иметь статический репозиторий. Просто сделайте его нестатическим и создайте его, когда вам это нужно.