Что такое хорошее соглашение об именах для универсальных типов в C #? [закрыто]

16

Я решил задать этот вопрос здесь вместо переполнения стека, потому что это довольно субъективно.

В C # обычно я вижу универсальные типы с очень плохими именами. В частности, «Т» обычно используется, но само по себе не является значимым именем. Например:

class Fruit<T>
{
    T fruit;
}

Хотя это типичный подход, кто-нибудь рекомендовал бы против этого? И если да, то каким будет разумное соглашение об именах для универсальных типов в контексте C # для универсальных функций и классов?

В моем предыдущем примере давайте предположим, что универсальный тип Tвсегда должен быть фруктовым, например, Appleили Orange. Тип Tдолжен сделать очевидным, что это фрукт, так что, может быть, лучше было бы назвать его лучше FruitType, так что в итоге мы получим:

class Fruit<FruitType>
{
    FruitType fruit;
}

Это просто, чтобы дать вам, ребята, представление о том, что я ищу. Что является приемлемым «практическим правилом» для этой проблемы?

void.pointer
источник
3
Это не конструктивный вопрос. Он получит ответы только в любимом стиле постера.
Майкл К
1
Посмотрите на ограничения, рассматривая ваш пример: msdn.microsoft.com/en-us/library/d5x73970.aspx#Y426
Матье
2
@ Майкл, будет несколько ответов, и принятый ответ станет любимым для Роберта, но за другие ответы будут проголосованы.
StuperUser
5
@ Майкл Субъективный вопрос получает субъективный ответ. Вопрос по-прежнему конструктивен, поскольку служит отправной точкой для тех, кто хочет разнообразить идеи / решения этой конкретной проблемы. Тот, который я отмечаю как ответ, не представляет единственную полезную информацию.
void.pointer
Может быть, превратить его в вики сообщества, как хороший, хотя и субъективный ресурс?
Tylermac

Ответы:

22

Это действительно субъективно ... иш .
Поскольку некоторые люди находят, что iэто совершенно верно для переменной цикла for, некоторые думают, что Tэто совершенно справедливо для заполнителя типа в универсальном классе.

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

Когда тип имеет смысл, я бы использовал значимое имя, но обычно начинаю его с T. Я недавно разработал общий словарный класс (не спрашивайте), и объявление было

public class Dictionary<TKey, TValue>

Однако для чего-то вроде Tuple, где типы по сути бессмысленны, я считаю следующее вполне приемлемым.

public class Tuple<T1, T2, T3>
Бинарный Беспорядок
источник
2
Я не считаю это субъективным вообще. iи Tработать, и это измеримо в принципе (то есть, измеримо, увеличивается ли понимание исходного кода, если, скажем, индексы цикла получают разные идентификаторы). Тот факт, что его трудно измерить, не означает, что мы должны пометить «субъективный» ярлык на всем. Учитывая широкое использование без очевидных проблем, вполне разумно сказать даже без оценки, что это действительно работает.
Конрад Рудольф
2
@ Конрад: у вас есть точка. , , однако вопрос не помечен как субъективный, спрашивающий признает, что это субъективная тема, предполагая, что люди, как правило, имеют свои собственные предпочтения в отношении соглашений об именах. Поэтому, хотя вопрос может быть не субъективным (а на самом деле это не так, поскольку существует правильный ответ, то есть ответ, который ссылается на официальное руководство Microsoft), тема носит субъективный характер, так как я уверен, что кто-то опубликует " iи Tявляются злом . никогда не следует использовать однонуклеотидных имена когда - либо» тип ответа. Добавили ish, чтобы помочь удовлетворить всех :)
Binary Worrier
1
Я думаю, что только комментарии, добавленные к этому сообщению, делают его очень ценным ответом, хотя сам ответ очень полезен. Tимеет смысл, когда мы говорим о типе без ограничений, TFruitимеет смысл, потому что он говорит мне: «Любой тип с ограничением, что это фрукт». Это похоже на хорошее «практическое правило» для именования параметров общего типа. Благодарность!!
void.pointer
1
Следует отметить, что это соответствует Руководству по проектированию .NET Framework для разработчиков библиотек из MSDN. См .: Имена параметров общего типа .
Грант Томас
7

Я думаю, что вы правы, хотя T стал довольно стандартным. Это, вероятно, происходит от старых времен C ++ и формулировки «типа T». Я считаю хорошей практикой быть как можно более описательной, но это субъективно.

Вы можете выбрать T в качестве префикса, так же, как многие люди выбирают I для интерфейсов. таким образом

class Juice<TFruit> where TFruit...

было бы хорошим именем по моему скромному мнению. Я предпочитаю префиксы суффиксам в большинстве случаев, так как сразу становится ясно, что вы видите, когда наталкиваетесь на них, и легче искать с такими вещами, как Intellisense. Это хорошая практика и для элементов управления пользовательским интерфейсом, когда вы, скорее всего, всегда знаете тип (например, TextBox), но не уверены на 100% в отношении описательного имени, которое вы ему дали.

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

class SomeAlgorithm<TypeT> where TypeT : Type

Обратите внимание, что это только мое мнение и очень субъективно. Но я думаю, что у меня есть небольшая точка с предпочтением префикса суффиксу.

сокол
источник
Использование Tпрефикса для параметров типа и Iдля имен интерфейсов явно требуется ( правила « DO ...») в Руководстве по проектированию платформы.
Ричард
1
Сомнительно, что использование TFruitздесь приводит к столу T. Использование имени, такого как TTypeили TypeT, конечно, глупость. Он не добавляет никакой информации просто T. Точно такая же информация передается.
Конрад Рудольф
@Konrad Rudolph: Посмотрите внимательно на мой пример TypeT, он охватывает особый случай при работе с System.Type. Я действительно думаю, что мои имена имеют более высокую энтропию, чем просто использование T для типа, особенно если родовой тип также ограничен.
Сокол
7

У Microsoft есть официальное руководство по дженерикам: названия классов, структур и интерфейсов (цитата здесь и в виде книги: Руководство по разработке структуры ).

Относительно вашего конкретного вопроса он говорит:

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

IDictionary<TKey, TValue> 

пример интерфейса, который следует этому руководству

Попробуйте использовать букву T в качестве имени параметра типа для типов с одним однобуквенным параметром типа.

У префикса описательного типа введите префикс имени буквы с буквой T.

Попробуйте указать ограничения, наложенные на параметр типа в имени параметра. Например, параметр, ограниченный ISession, может называться TSession.

Матье
источник
Лучшим справочником будет книга « Руководство по разработке структуры» или (краткое изложение) по MSDN, в частности, по именам классов, структур и интерфейсов .
Ричард
@Richard: скорректировал мой ответ, учитывая ваш комментарий, спасибо!
Матье
2

Весь смысл обобщений заключается в делегировании функциональности - универсальный класс делает одно, а его аргумент - другое. Пример из учебника является общей коллекцией: коллекция хранит «вещи», но ей все равно, что это за вещи. Таким образом, универсальное имя (sic!) Имеет определенную логику - мы не хотим, чтобы оно было описательным, потому что нет ничего, что можно описать, кроме как «это аргумент универсального типа», которое имя Tохватывает полностью (учитывая конвенция). Быть описательным - это хорошо, но чрезмерно описательное предполагает ограничения, которых нет.

Однако иногда универсальный класс или метод имеет более одного параметра типа, и на этом этапе имеет смысл дать им более описательные имена, чтобы их роль стала очевидной. Хорошим примером может служить тип коллекции ключ-значение, где и ключ, и значение являются общими; называть их Tи S(или Qили как угодно) было бы менее полезно, чем называть их, скажем, KeyTypeи ValueType, или, TKeyи TVal.

tdammers
источник
1

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

Ниже приведены правила, которые я выучил и которым я следую

  • Параметры общего типа никогда не должны ошибочно приниматься за конкретные классы. Это обычно поощряет предисловие, Tнезависимо от того, что следует, во многом как интерфейсы, как правило, предваряются I.

  • Один параметр универсального типа в классе или методе обычно должен быть помечен T. Это почти универсально понятное соглашение, восходящее к шаблонам C ++.

  • Несколько параметров универсального типа в одном и том же объявлении класса или метода должны начинаться с буквы T, но различаться с помощью некоторых кратких, но понятных средств. TInи TOut, например, являются общими и хорошо понятными GTP для метода, который принимает строго типизированный общий ввод и производит строго типизированный общий вывод.

  • Множественные дифференцированные, но ничем не примечательные типы, например, для содержащего класса, такого как Tuple или типы делегатов .Net, такие как Func, Predicate и Action, могут быть помечены как T1, T2, T3 и т. Д. Однако «замечательные» объявления GTP (имеющие определенное назначение и / или очень специфические ограничения типа) должны иметь что-то более описательное.

  • Один универсальный тип в методе, который отличается от универсального типа содержащего класса, может либо следовать предыдущему правилу, касающемуся нескольких типов в классе или методе, ИЛИ, если тип является ничем не примечательным, кроме того, что ему может быть присвоен другой одна буква, часто Uили V. Это снова соглашение, восходящее к шаблонам C ++.

  • Что бы вы ни выбрали, сохраняйте это последовательным; не помечайте GTP для одного класса Tи для следующего TParam, если только второй класс не вложен в первый, что делает Tнедоступным для использования во втором.

Keiths
источник