Подтвердить что ты не робот

С# интерфейс и реализация в том же файле - хорошая идея?

Недавно я увидел некоторый код С#, где декларация интерфейса и реализация, где в том же файле, например,

namespace MyNameSpace.Foo
{
    public interface IFoo{
        void DoThis();
    }
    public class Foo : IFoo {
        public void DoThis();
    }
}

На первый взгляд кажется неправильным иметь декларацию и реализацию в одном файле, но есть практические преимущества. например Когда вы переходите к определению в Visual Studio, интерфейс и реализация находятся в одном файле. Этот подход не запрещает вам выполнять другие реализации интерфейса, например, может потребоваться для модульного тестирования. Для интерфейсов, которые будут только одной реализацией, я думаю, что это может быть прагматичным подходом.

Хорошая или плохая идея?

Продление вопроса:
Как люди используют Visual Studio для перехода к реализации, когда у вас есть ссылка на интерфейс IFoo myFoo = FooFactory.getFoo(MY_FOO); Если я нажимаю правой кнопкой мыши на IFoo и выбираю Go To Definition, я могу получить декларацию интерфейса. Есть ли способ получить список реализаций IFoo как того, к чему я действительно заинтересован.

4b9b3361

Ответ 1

Моя рекомендация - всегда следовать правилу одного элемента за файл .cs, будь то объявление перечисления, интерфейс или класс. Имя файла .cs должно совпадать с именем содержащейся в нем вещи.

Простое правило, легко следовать. Мы используем StyleCop для защиты от этого.

Если вы комбинируете этот подход с разумным использованием пространств имен, то это должно означать, что ваше представление проводника решений в Visual Studio упрощает навигацию по компонентам ваших проектов. Обратите внимание, что ReSharper дает альтернативный подход к этой навигации, но использование этого не для всех вкусов (и не у каждого может быть надстройка, такая как ReSharper).

Тревис G спросил о более тонких точках, таких как делегаты и пользовательские объявления EventArgs. Поскольку пользовательские EventArgs являются классами, я бы поместил их в свои собственные файлы (опять же, сохраняя правило простым). Делегаты я объявляю с классом, который их использует. Если бы я обнаружил, что у меня было много делегатов, которые использовались во многих местах, я мог бы рассмотреть их размещение в файле Delegates.cs(иногда я делаю это с константами в файле Consts.cs).

Однако некоторые из них, безусловно, субъективны и попадают в сферы программного обеспечения религиозные войны.

Ответ 2

Лично...

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

Конечно, если есть вероятность, что интерфейс будет реализован более чем одним классом, я поместил его в отдельный файл.

Ответ 3

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

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

Ответ 4

Я рассматриваю это как плохую идею.

Разделите интерфейс и реализацию. В противном случае вы можете испортить дизайн. Включите файл и автоматически получите реализацию, даже если вам нужен только интерфейс, а затем случайно (потому что это удобно) используйте Impl вместо интерфейса и yay, близкую связь.

Ответ 5

Я бы просто придерживался правила "один класс, один файл". С классом я также подразумеваются интерфейсы, перечисления и т.д.

И что не так с помещением курсора на имя интерфейса и нажатием F12?

Ответ 6

Уверен, что это не вредно, если бы это было так, и такие инструменты, как resharper, помещают реализацию под интерфейсом в код. Однако они также дают вам возможность перенести реализацию в другой файл.

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

Ответ 7

Я делаю это в java для небольших интерфейсов с несколькими методами. В этом случае я предоставляю одну или несколько базовых реализаций в файле интерфейса.

Это предотвращает рассеяние маленьких классов.

Но я не могу сказать, если это плохой или лучший опыт, хотя мои коллеги никогда не жаловались.