Как лучше всего хранить группу констант, которые использует моя программа? [закрыто]

97

У меня есть различные константы, которые моя программа использует ... string's, int' s, double's, и т.д ... Как лучше всего их хранить? Я не думаю, что мне нужен Enum, потому что все данные не одного типа, и я хочу вручную установить каждое значение. Должен ли я просто хранить их все в пустом классе? Или есть способ лучше?

Мэтью
источник
18
Как бы вы ни хотели - вот как вам это нужно.
Сан-Хасинто,

Ответы:

135

Вы, вероятно, могли бы иметь их в статическом классе со статическими свойствами только для чтения.

public static class Routes
{
    public static string SignUp => "signup";
}
Дэниел А. Уайт
источник
23
+1, но еще лучше, если вы можете извлечь их из файла ресурсов для локализации.
Joel Coehoorn
17
Кажется немного многословным - почему не статические строки только для чтения?
emptyset
6
Почему readonly, а не const? Вы не устанавливаете значение во время выполнения, поэтому нет необходимости иметь их только для чтения.
Филип Уоллес,
91
Проблема с константой заключается в том, что любые сборки, скомпилированные с константами, получают локальные копии этих констант, когда сами компилируются; поэтому, если вы измените значение, вы также должны перекомпилировать все сборки, зависящие от вашей сборки, определяющей константы, поэтому часто безопаснее идти по маршруту только для чтения. Свойства вместо общедоступных статических значений дают вам гибкость для добавления некоторой логики программирования в будущем, если она вам понадобится (например, чтение из локализации), без изменения интерфейса на ваши постоянные значения.
cfeduke
11
Как сторонник дьявола, я должен отметить, что преимущество const в том, что вы можете использовать ее в случаях переключения.
arviman
27

IMO, использующий класс, полный констант, подходит для констант. Если они будут время от времени меняться, я рекомендую вместо этого использовать AppSettings в вашей конфигурации и класс ConfigurationManager.

Когда у меня есть «константы», которые фактически извлекаются из AppSettings или подобного, у меня всегда будет класс «констант», который завершает чтение из диспетчера конфигурации. Всегда более значимо иметь Constants.SomeModule.Settingвместо того, чтобы обращаться напрямую в ConfigurationManager.AppSettings["SomeModule/Setting"]любое место, которое хочет использовать указанное значение настройки.

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

Крис Маришич
источник
1
Просто добавлю: причина в том, что при сборке константы, используемые из других сборок, не обновляются. Это означает, что если у вас есть AssemblyA и AssemblyB, а B использует константу из A, значение копируется, а не ссылается, поэтому повторная сборка A не обновит B. Это может привести к странным ошибкам.
Камило Мартин
1
@CamiloMartin много способов справиться с этим, ваши «константы» могут просто статические только для чтения, чтобы избежать этого, или, как я уже сказал, если они меняются более одного раза в синюю луну, для использования ConfigurationManager.
Крис Марисич,
Да, я просто сказал, что это не только потому, что это соглашение, что вы должны использовать static только для чтения, но и потому, что это действительно может быть источником путаницы. Кроме того, альтернативой ConfigurationManager являются файлы ресурсов - вам просто нужно добавить еще один файл ресурсов с языковым кодом в имени, и ваш код мгновенно локализуется.
Камило Мартин,
проблема в том, что когда вы ссылаетесь на эту сборку из других сборок, вам придется копировать значения в их файлы конфигурации
симбионт
@symbiont, вы можете встроить файлы конфигурации и вместо этого читать их из манифеста, если хотите, для возможности совместного использования в качестве стороннего компонента
Крис Марисик
19

Мне нравится делать следующее (но обязательно прочитайте до конца, чтобы использовать правильный тип констант ):

internal static class ColumnKeys
{
    internal const string Date = "Date";
    internal const string Value = "Value";
    ...
}

Прочтите это, чтобы узнать, почему это constможет быть не то, что вам нужно. Возможные типы констант :

  • constполя. Не используйте для разных сборок ( publicили protected), если значение может измениться в будущем, потому что значение будет жестко закодировано во время компиляции в этих других сборках. Если вы измените значение, старое значение будет использоваться другими сборками, пока они не будут повторно скомпилированы.
  • static readonly поля
  • static собственность без set
Марсель Госселен
источник
1
Почему только для чтения, если используется в нескольких сборках?
Филип Уоллес,
Почему static readonly лучше работает с несколькими сборками, чем const?
Matthew
15
Значения Const копируются из исходной сборки в скомпилированный код. Это означает, что если вам нужно изменить значение const, все зависимые сборки ДОЛЖНЫ быть перекомпилированы для новой версии. Безопаснее и удобнее использовать статические файлы только для чтения.
cfeduke
6
Преимущества const в том, что их можно использовать в переключателе
knaki02
11

Это лучший способ ИМО. Нет необходимости в свойствах или только для чтения:

public static class Constants
{
   public const string SomeConstant = "Some value";
}
Филип Уоллес
источник
9
Если вы собираетесь использовать const, выставляйте только как внутренний. Не делайте const общедоступным (даже если вы думаете, что ваши сборки не будут использоваться вне вашей организации). Кроме того, свойства дают вам программную гибкость для будущего расширения без необходимости переопределять интерфейс.
cfeduke
4

Подходит пустой статический класс. Рассмотрите возможность использования нескольких классов, чтобы получить хорошие группы связанных констант, а не один гигантский файл Globals.cs.

Кроме того, для некоторых констант типа int учтите следующие обозначения:

[Flags]
enum Foo
{
}

Так как это позволяет обрабатывать значения как флаги .

пустой набор
источник
«Подумайте об использовании нескольких классов, чтобы получить хорошие группы связанных констант, а не один гигантский файл Globals.cs». Я считаю, что это лучшая рекомендация, разве нет никаких шаблонов проектирования? Я не знаю никого по имени, а вы?
greg
3

Еще один голос за использование web.config или app.config. Конфигурационные файлы - хорошее место для констант, таких как строки подключения и т. Д. Я предпочитаю не смотреть на исходный код, чтобы просматривать или изменять такие вещи. Статический класс, который считывает эти константы из файла .config, может быть хорошим компромиссом, так как он позволит вашему приложению получать доступ к этим ресурсам, как если бы они были определены в коде, но все же дает вам гибкость, позволяя их легко просматривать / редактировать. пространство.

3Dave
источник
2
Строка подключения - это не константа, это параметр. Возможно, OP действительно означает и настройки, а не константы, но я не вижу никаких доказательств этому.
Джон Скит,
Позволю себе не согласиться. Строковые литералы по определению являются константами. Изменение строки в файле конфигурации примерно эквивалентно ее изменению в коде и перекомпиляции; Would , что не делает его константу? Я так не думаю.
3ave
2
@ Дэвид - Неправда. Компилятор не заботится о том, какое значение у вас есть в вашем файле конфигурации - это читается во время выполнения.
Филип Уоллес,
@PhilipW Я понимаю это. Я хотел сказать, что (в ответ на комментарий Джона Скита) конкретная строка подключения является константой, как и все строковые литералы. Тот факт, что «константа» может быть изменена - будь то путем изменения файла конфигурации и получения вашим приложением нового значения из указанного файла конфигурации, или путем изменения литерала в коде, который потребует перекомпиляции / развертывания, - не сделайте это «сеттингом». Сама строка постоянна независимо от ее контейнера. Я понимаю и согласен с вашей точкой зрения - я просто не это говорил.
3ave
1
По моему опыту, в какой-то момент в непредвиденном будущем ваша «постоянная» ценность должна будет измениться, даже если вы думали, что этого никогда не произойдет через миллион лет. Я думаю, что это намного проще сделать в файле .config, чем изменять исходный код. В конце концов, все становится сеттингом.
NinjaBomb
1

Да, вполне static classподойдет a для хранения констант, за исключением констант, относящихся к определенным типам.

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

Если эти константы являются ссылками на службы или переключателями, которые влияют на поведение приложения, я бы установил их как пользовательские настройки приложения. Таким образом, если их нужно изменить, вам не нужно перекомпилировать, и вы все равно можете ссылаться на них через класс статических свойств.

Properties.Settings.Default.ServiceRef
Аарон
источник
0

Я бы предложил статический класс со статическим только для чтения. Найдите фрагмент кода ниже:

  public static class CachedKeysManager
    {
        public static readonly string DistributorList = "distributorList";
    }
КАПИЛ ШАРМА
источник