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


14

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

MyClass<T1>
MyClass<T1, T2>
MyClass<T1, T2, T3>

Учитывая, что я хочу все это в одном пространстве имен, я не понимаю, как структурировать и назвать мои классы и файлы?

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

Что я действительно спрашиваю здесь, это то, что я должен назвать файл, который содержит MyClass<T1>, и как я должен назвать файл, который содержит MyClass<T1, T2>? Я не спрашиваю, какими должны быть имена параметров типа.


Приведите нам несколько конкретных примеров, которые описывают проблему более подробно. Приведенные вами примеры слишком ... ну, общие. Что вы подразумеваете под "как структурировать и назвать мои классы и файлы?"
Роберт Харви

Microsoft делает это самостоятельно, просто добавляя число к параметру типа. См. Документы Tuple: msdn.microsoft.com/en-us/library/…
Пит

@ Пит: Это действительно относится только к Tuple. Microsoft также использует TKey, TValueсоглашение. У Func есть TResultпараметр типа. Хотя я согласен , что вы можете использовать T1, T2и т.д. для переменного числа входных параметров , которые в противном случае не имеют конкретных целей , как TKeyи TValue.
Роберт Харви

@RobertHarvey Хорошо, да, но только в контексте фактической коллекции ключ / значение, такой как словарь. Для чего-либо, состоящего из переменного числа типов, они добавляют число. Вот еще один пример: msdn.microsoft.com/en-us/library/dd402872(v=vs.110).aspx
Пит

1
Ну, ваши изменения устарели некоторые комментарии. :) Почему вы не можете просто держать классы в одном физическом файле? Если они настолько разные, что вам нужно хранить их в отдельных файлах, то можете ли вы сказать нам, чем они отличаются?
Пит

Ответы:


14
MyGenericClass`1.cs
MyGenericClass`2.cs
MyGenericClass`3.cs

И так далее, где число после обратного кавычка - это число параметров универсального типа. Это соглашение используется Microsoft.

Кроме того, вы можете использовать что-то вроде

MyGenericCollectionClass[TKey, TValue].cs

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


1
Компилятор внутренне изменяет имя универсальных типов, добавляя обратный тик и число универсальных параметров, поскольку .NET не допускает использование нескольких типов с одним и тем же именем с различным количеством универсальных параметров, но в C # - нет. Таким образом, соглашение об именовании файлов соответствует тому, что делает компилятор.
CodesInChaos

1
Я хотел доказать, что вы не правы, но на самом деле вы правы: github.com/dotnet/corefx/tree/master/src/… Мне не нравится это соглашение.
День

1
@ Ден, кажется, что теперь они сожалеют об этом соглашении. Может быть, это подразумевает какую-то проблему? github.com/dotnet/corefx/commit/…
Сэм

@Sam Надеюсь, не проблема связи между командами Microsoft. Потому что никто больше этим не занимается. На мой взгляд, решать должна команда компиляторов, а не библиотека.
День

У меня не было бы шаров для использования "` "в имени файла.
Кристиан Э.

4

В случае Tupleи Actionчто Пит отметил, Microsoft сами используют единый файл - см Tuple.cs и Action.cs .

Я думаю, что это частично зависит от того, одинаковы ли функциональные возможности для всех классов. Лично мне не нравится объединять классы в один файл, но это может быть исключением. В исходный код, где я работаю, я добавил автоматически сгенерированный (используя T4) NamedTupleкласс, который действует так же, как Tupleи строковое имя в качестве первого аргумента в конструкторе.

Чтобы ответить на ваш вопрос, если вы не хотите использовать один файл, возможно, используйте MyClass_1.cs для MyClass<T1>, MyClass_2.cs для MyClass<T1, T2>и т. Д.

Однако ни один из этих вариантов не является идеальным, поэтому я был бы склонен предложить аргумент «Microsoft делает это таким образом, так что ...».


2
Tupleи Actionвсе делегаты; у них нет никакого кода реализации, поэтому помещать все варианты в отдельные файлы было бы в любом случае бессмысленно. Просто доказывает, что каждое правило имеет исключение.
Роберт Харви

Да, вообще говоря, размещение нескольких открытых делегатов в одном файле считается нормальным (при условии, что они связаны).
Стивен

1
@RobertHarvey, Tupleне является делегатом, но каждая реализация в любом случае коротка.
Артуро Торрес Санчес

@ ArturoTorresSánchez: Правильно, я думал о Func.
Роберт Харви

0

Вы спрашивали себя, действительно ли у классов такое же намерение? Если один класс является более универсальным, чем другой, то это будет GenericClass , MoreGenericClass и MostGenericClass . Представьте, что каждый параметр типа класса добавляет новое измерение в класс, так что это может помочь выяснить, что это за измерение.

Давайте возьмем этот пример:

  • Container<Thing>
  • MetricContainer<Thing, Metric>
  • MetricTransportableContainer<Thing, Metric, Transport>

Я знаю, что это не лучший пример, но очень выразительно, чтобы показать три измерения:

  • Внутреннее измерение, что он может загрузить
  • Размер метрики, с помощью которого она может быть загружена, только по количеству вещей или по квадратной мере, или по кубической емкости, или по весу.
  • внешнее измерение, где оно может быть загружено.

Таким образом, вы можете моделировать перевозки автомобилей:

Container<Cars>
MetricContainer<Cars, CountMetric>
MetricTransportableContainer<Cars, CountMetric, Ship>

Перевозка жидкостей:

Container<Fluid>
MetricContainer<Fluid, Volume>
MetricTransportableContainer<Fluid, Volume, Shelf>

Транспортировка энергии:

Container<Energy>
MetricContainer<Energy, ElectricPower>
MetricTransportableContainer<Energy, ElectricPower, Box>

Перевозка сахара, крупы:

Container<CrumblyMaterial>
MetricContainer<CrumblyMaterial, Weight>
MetricTransportableContainer<CrumblyMaterial, Weight, Silo>

О, какой сюрприз: a List<T>имеет одно измерение, представляющее то, что может содержать список; и это Map<T, S>с двумя измерениями, которые представляют вещи, которые может содержать карта, и ключи доступа.


1
Я не думаю, что вы поняли вопрос. Посмотрите на последний абзац вопроса.
Роберт Харви

1
@RobertHarvey Пожалуйста, внимательно прочитайте вопрос: имя класса должно совпадать с именем файла. Это взаимозаменяемо. Проблема заключается в неправильном анализе класса и неправильном именовании общих классов в целом. Подводя итог моему ответу: «Назови это, что это такое, а не то, что кажется».
shylynx


1
@RobertHarvey Прочитайте мой ответ: поместите один класс в один файл!
shylynx

1
Я думаю, что вы упускаете суть. Вопрос спрашивает: Как я кладу Tuple<T1>, Tuple<T1, T2>и Tuple<T1, T2, T3>в отдельные файлы CS стандартным способом, без имен столкновений?
Роберт Харви
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.