В чем причина соглашения именования префиксов «I» для интерфейсов в .NET?

10

Я знаю, что соглашение «I» существует со времен COM, но я никогда не понимал, почему оно не было пересмотрено, как любое другое соглашение об именах до .NET.

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

Я также подумал, что это может быть так, что у вас может быть базовая реализация интерфейса с тем же именем, например Messageнаследование IMessage, но большинство библиотек .NET пошли для добавления слова «Base» в конце (например System.Collections.ReadOnlyCollectionBase) вместо этого - и это имеет более смысловой смысл.

COM-взаимодействие, кажется, еще одна возможная причина - но не то, чтобы создаваемые им классы-обертки были совершенно идиоматичными .NET, поэтому я сомневаюсь, что это было эстетическим соображением.

В одном из моих новых проектов я полностью отказался от соглашения, и это прекрасно. Я что-то пропустил?

Рей Миясака
источник
1
Вы не наследуете интерфейсы для их выполнения, большая разница.
Дэниел Литтл
Также это похоже на предпочтения, такие как IList и List, в отличие от List и ArrayList. Вероятно, они сделали это, потому что IList не ListBase, а действительно ListInterface (не интерфейс типа List), если вы понимаете, о чем я.
Даниэль Литтл
@Lavinski В .NET IListявляется общим термином для секвенировали, смежный сбор, произвольный доступа, в то время как Listэто секвенировали, непрерывный, случайный доступ, растет сбор. Я думаю, что F # имел право в псевдониме Listк ResizeArray; это определенно гораздо более описательное имя. IListтогда могло бы быть List, так что не похоже, что это тоже будет причиной.
Рей Миясака
2
IBaseBall и IBaseBallBase имеют для меня больше смысла, чем BaseBallBase и BaseBallBaseBase (глупый пример, я знаю: D)
e-MEE
@ e-MEE такой же глупой была бы IIRC, которая могла бы быть интерфейсом для протокола чата IRC, или аббревиатура для «если я правильно помню».
Рей Миясака

Ответы:

12

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

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

public sealed class ActivityCollection : List<Activity>, 
    IList<Activity>, ICollection<Activity>, IEnumerable<Activity>, 
    IList, ICollection, IEnumerable

Было бы сложнее понять, если бы определение выглядело как

public sealed class ActivityCollection : ListClass<Activity>, 
    List<Activity>, Collection<Activity>, Enumerable<Activity>, 
    List, Collection, Enumerable

А как бы ты позвонил ListClass? Очевидно, что это не только ListBaseпотому, что его можно использовать само по себе.
Поэтому нам нужно либо решить проблему, которую мы только что изобрели, либо адаптировать префикс, отделяющий классы от интерфейсов, что и сделали дизайнеры .NET Framework.

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

public void PrintLines (IEnumerable<string> source)

Это как сигнал моей голове: эй, я могу это реализовать! Я могу кормить метод всем, что соответствует контракту.

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

Кстати, не только интерфейсы имеют префиксы в системе типов .NET. Не забудьте о параметрах универсального типа:

public delegate TResult Func<in T, out TResult>(
    T arg
)

Это еще одна ситуация, когда чрезвычайно полезно различать классы и типы других типов.

Дэн
источник
2
Вы можете легко понять, что, зная, что «первый класс является наследованием, второй класс и далее являются интерфейсами».
Саид Нямати
3
Это похоже на правдоподобную причину. Java , кажется, решил его немного более красиво, просто используя ключевые слова , чтобы уточнить список: class Dog extends Mammal implements MailmanChaser. @Seed, у вас может быть класс, который ни от чего не наследуется, поэтому первый тип в списке на самом деле является интерфейсом, а не базовым классом.
Рей Миясака
+1 для части, выделенной жирным шрифтом, хотя я могу вспомнить другое место, где было бы полезно соглашение на основе префиксов: различать поле, которое инкапсулирует исключительное владение int[](или другим объектом изменяемого типа), которое оно может изменять, но не может share, и тот, который инкапсулирует совместное владение, int[]что, хотя его тип допускает мутации, никто не может мутировать.
суперкат
6

Я не думаю, что вы ничего не упустили, это просто историческая привычка.

Я также согласен с вами, а также отбросил «я» на пару небольших и средних проектов без какого-либо вредного воздействия.

Крис Ли
источник
2
Что странно, так это то, что они выбросили практически все устаревшие соглашения, кроме этого. История тоже не совсем это объясняет. Я все еще чувствую, что, должно быть, была причина, если это действительно не была внутренняя политика - но даже тогда я действительно не вижу причины, чтобы кто-то расстроился из-за того, что меня уволили.
Рей Миясака
2

Я думаю, что единственная причина, согласно Руководству Microsoft по именованию интерфейсов и классов , заключается в том, что иногда возникают конфликты между именем интерфейса и реализующим его классом. Это восходит к тому факту, что интерфейсы на самом деле являются каркасом, а не мясом, а класс реализатора на самом деле является мясом (реализуя план). Таким образом, IAnimal описывает только то, что должно быть у животного , а Animal может сказать вам, что у него есть .

Тем не менее, я лично полностью согласен с вами в том, что мы можем просто использовать Animal Base для интерфейса и Animal для класса.

С другой стороны, иногда две вещи настолько сильно противоречат друг другу, что команда решает выработать соглашение для предотвращения дальнейших конфликтов, несмотря на уже принятые решения. Например, в ASP.NET MVC и частичные представления, и макеты (главные страницы) аналогичны обычным представлениям , хотя и выполняют разные функции. Таким образом, Microsoft, несмотря на то, что подчеркивает, что не следует использовать подчеркивание в именовании, предлагает подчеркивать компоновки и частичные представления подчеркиванием.

Саид Нямати
источник
Что не так AnimalInterfaceвместо AnimalBase? Это не базовый класс, это интерфейс.
Скотт Уитлок
3
но что не так с IAnimal вместо AnimalInterface? конечно, мы прошли весь путь до того, с чего начали - что просто показывает, что некоторые «венгерские» нотации были полезны. Выбросить их всех (кроме меня и Т) было скорее досадой, чем вдумчивой попыткой найти лучшую систему.
gbjbaanb
2
@ ScottWhitlock: для меня IAnimalэто гораздо более читабельно, чем AnimalInterface. Подробные имена предпочтительнее, за исключением случаев, когда простое короткое соглашение может использоваться для чего-то, что происходит достаточно часто. И интерфейсы - такой случай.
Maaartinus