Який найкращий спосіб зберігати групу констант, які використовує моя програма? [зачинено]


97

У мене є різні константи, які використовує моя програма ... string, ints, doubles тощо ... Який найкращий спосіб їх зберігати? Я не думаю, що хочу Enum, оскільки дані не всі однотипні, і я хочу вручну встановити кожне значення. Чи слід просто зберігати їх усіх у порожньому класі? Або є кращий спосіб?


18
Будь-яким чином ти хочеш - це те, що тобі потрібно.
Сан-Хасінто

Відповіді:


135

Можливо, ви могли б мати їх у статичному класі зі статичними властивостями лише для читання.

public static class Routes
{
    public static string SignUp => "signup";
}

23
+1, але ще краще, якщо ви можете витягти їх із файлу ресурсу для локалізації.
Джоел Коухорн,

17
Здається, трохи словно - чому не статичні рядки лише для читання?
emptyset

6
Чому лише для читання, а не const? Ви не встановлюєте значення під час виконання, тому немає необхідності мати їх лише для читання.
Філіп Уоллес,

91
Проблема const полягає в тому, що будь-які збірки, скомпільовані проти consts, отримують локальні копії цих consts, коли вони самі компілюються; тому, якщо ви змінюєте значення, ви також повинні перекомпілювати всі збірки, що залежать від вашої збірки, визначаючи константи - тому часто безпечніше пройти шлях лише для читання. Властивості замість загальнодоступних статичних значень дають вам можливість надалі додавати деяку логіку програмування, якщо вам це потрібно (тобто читати з локалізації), не змінюючи інтерфейс на ваші постійні значення.
cfeduke

11
Як адвокат диявола, я повинен зазначити, що перевага const полягає в тому, що ви можете використовувати його у випадках перемикання.
arviman

27

ІМО, використовуючи клас, повний констант, чудово підходить для констант. Якщо вони періодично змінюватимуться, я рекомендую використовувати натомість AppSettings у вашій конфігурації та класі ConfigurationManager.

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

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


1
Додамо лише до цього: причина полягає в тому, що при побудові константи, що використовуються з інших збірок, не оновлюються. Це означає, що якщо у вас AssemblyA і AssemblyB і B використовує константу з A, значення копіюється, а не посилається, тому повторна побудова A не оновлює B. Це може призвести до дивних помилок.
Каміло Мартін

1
@CamiloMartin безліч способів впоратися з цим, ваші "константи" можуть просто статичні readonlys, щоб уникнути цього, або, як я вже говорив, якщо вони змінюються більше одного разу в синій місяць, щоб використовувати ConfigurationManager.
Chris Marisic

Так, я просто говорив, що це не просто тому, що це умова, що ви повинні використовувати статичне читання, а тому, що насправді це може спричинити плутанину. Крім того, альтернативою ConfigurationManager є файли ресурсів - вам просто потрібно додати ще один файл ресурсу з мовним кодом в назві, і ваш код миттєво локалізується.
Каміло Мартін

проблема полягає в тому, що коли ви посилаєтесь на цю збірку з інших збірок, вам доведеться скопіювати значення у їхні конфігураційні файли
symbiont

@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
Навіщо читати лише при використанні в декількох збірках?
Філіп Уоллес,

Чому статичне читання працює краще з кількома збірками, ніж const?
Метью

15
Значення const копіюються з вихідної збірки в скомпільований код. Це означає, що якщо вам потрібно змінити значення const, усі залежні збірки ПОВИННІ перекомпілювати до нової версії. Безпечніше та зручніше використовувати статичні читання.
cfeduke

6
Переваги const в тому, що їх можна використовувати в комутаторі
knaki02

11

Це найкращий спосіб IMO. Немає необхідності у властивостях або лише для читання:

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, може бути хорошим компромісом, оскільки він дозволить вашій програмі отримувати доступ до цих ресурсів, як якщо б вони були визначені в коді, але все одно надає вам гнучкість їх розміщення у легко переглядається / редагованому простору.


2
Рядок з'єднання - це не константа, це налаштування. Можливо, OP справді означає і настройки, а не константи, але я не бачу жодних доказів для цього.
Джон Скіт,

Дозволю собі не погодитися. Рядкові літерали - це константи за визначенням. Зміна рядка у файлі конфігурації приблизно еквівалентна зміні його в коді та перекомпіляції; Would , що робить його константу? Я не думаю, що так.
3Dзберегти

2
@David - Неправда. Компілятору все одно, яке значення у вас є у вашому конфігураційному файлі - це читається під час виконання.
Філіп Уоллес,

@PhilipW Я це розумію. Моя думка полягала в тому, що (у відповідь на коментар Джона Скіта) конкретний рядок зв’язку є константою, як і всі рядкові літерали. Те, що "константу" можна змінити - змінивши файл конфігурації та змусивши програму витягнути нове значення із зазначеного конфігураційного файла, або змінивши буквальний код у коді, який потребував би перекомпіляції / розгортання - не означає зробіть це "налаштуванням". Сам рядок є константою незалежно від його контейнера. Я розумію і погоджуюся з вашою думкою - це було не те, що я говорив.
3Dave

1
З мого досвіду, в якийсь момент у непередбаченому майбутньому ваше "постійне" значення потрібно буде змінити, навіть якщо ви думали, що цього не станеться через мільйон років. Я думаю, що це зробити набагато простіше у файлі .config, ніж зміна вихідного коду. Врешті-решт все стає обстановкою.
NinjaBomb

1

Так, static classдля зберігання констант було б чудово, за винятком констант, які відносяться до певних типів.


це саме те, що я намагаюся зробити. Я хочу, щоб вони показали себе членами класу, для якого вони є. але я не хочу додавати їх до класів, оскільки константи змінюються залежно від компанії, в якій я роблю роботу. я ще не знайшов нічого про константи розширення або властивості. але я міг би відмовитись від цієї ідеї, тому що я не хочу, щоб вони з'являлись як члени, коли я серіалізую ці класи
симбіонт

0

Якщо ці константи є посиланнями на послуги або перемикачами, які впливають на поведінку програми, я б встановив їх як налаштування користувача програми. Таким чином, якщо їх потрібно змінити, вам не потрібно перекомпілювати, і ви все ще можете посилатися на них через клас статичних властивостей.

Properties.Settings.Default.ServiceRef

0

Я б запропонував статичний клас зі статичним readonly. Знайдіть фрагмент коду нижче:

  public static class CachedKeysManager
    {
        public static readonly string DistributorList = "distributorList";
    }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.