C # Статический класс против структуры для предопределенных строк - PullRequest
48 голосов
/ 08 февраля 2010

Сотрудник только что создал следующую конструкцию в C # (пример кода упрощен). Его целью было сократить нотацию для всех предопределенных строк в остальной части кода.

public struct PredefinedStrings
{
    public const string VeryLongName = "Very Long Name";
    public const string AnotherVeryLongName = "Another Very Long Name";
    public const string TheLastVeryLongName = "The Last Very Long Name";
}

public static void MethodThatUsesTheNames()
{
    Console.WriteLine(PredefinedStrings.VeryLongName);
    Console.WriteLine(PredefinedStrings.AnotherVeryLongName);
    Console.WriteLine(PredefinedStrings.TheLastVeryLongName);
}

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

Какой предпочтительный способ сделать это? Пожалуйста, объясните, почему.

Ответы [ 13 ]

42 голосов
/ 08 февраля 2010

С решением struct ничто не мешает другому коду, выполняющему new PredefinedStrings(), который не будет делать что-то плохое , но это то, что семантически запутанно допускать. Со статическим классом компилятор запретит вам создание. И само собой разумеется, что статический класс является предпочтительным способом предоставления констант в Framework.

edit чтобы добавить, я сказал, что вторая часть без доказательств - с тех пор я искал и довольно быстро нашел System.Net.Mime.DispositionTypeNames и System.Net.WebRequestMethods.Http.

31 голосов
/ 08 февраля 2010

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

25 голосов
/ 08 февраля 2010

Кроме static class и struct, почему бы не рассмотреть возможность использования файлов resource для константных строк? К ним можно очень легко получить доступ как SomeNamespace.ResourceName.KeyName, и в зависимости от того, где они находятся в вашем проекте, можно управлять внешним образом без перекомпиляции, если это необходимо ...

9 голосов
/ 08 февраля 2010

Простое правило: никогда не используйте структуры, пока у вас нет другого выбора.

Константы имеют пару недостатков:

  • могут использоваться только простые типы (строки, числа и т. Д.)
  • константы вводятся в ссылочные сборки. Если вы перекомпилируете сборку с константами и не перекомпилируете сборку с использованием констант, у вас возникнут проблемы

Я бы написал ваш код следующим образом (обратите внимание, что также переименуйте рефакторинг):

public static class KnownNames
{
    public static readonly string VeryLong = "Very Long Name";
    public static readonly string AnotherVeryLong = "Another Very Long Name";
    public static readonly string TheLastVeryLong = "The Last Very Long Name";
}
6 голосов
/ 08 февраля 2010

Похоже, вы ищете файл ресурсов (.resx). Это подходящее место для хранения таких строк, и абстрагирование ваших строк в .resx облегчит локализацию вашего приложения в будущем. Страница MSDN на http://msdn.microsoft.com/en-us/library/1ztca10y.aspx является хорошим началом для получения дополнительной информации.

5 голосов
/ 08 февраля 2010

Не забывайте рекомендацию, что размер структуры должен быть около 16 байтов. Для 32-битной системы это 4 ссылки на System.String. Я бы сказал, что вам лучше использовать статический класс, если число строк увеличится.

5 голосов
/ 08 февраля 2010

Функционально в этом коде нет ничего плохого. Но стилистически я согласен, что статический класс лучше. Статический класс объявляет, что целью типа является хранение только статических / постоянных данных.

2 голосов
/ 27 июня 2015

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

Поскольку ваш коллега не использует его для хранения значения, он должен использовать класс, а не структура.

1 голос
/ 27 декабря 2014

статический класс, кажется, лучший путь, потому что он самый стандартный и ожидаемый. Я думал, что версии struct / const могут быть быстрее, но после некоторых тестов они не были.

Вот результаты моего быстрого теста, который включал длину, сравнение, конкат, копирование, indexOf и подстроку. Он был запущен в версии .Net 4.0 без отладчика.

                                          .Net 3.0  .Net 4.0
static class with static read-only string:  0.217   0.364  seconds
static class with const            string:  0.211   0.361  seconds
struct       with static read-only string:  0.211   0.372  seconds
struct       with const            string:  0.214   0.371  seconds
Properties.Resources               string:  1.173   1.268  seconds

Все они были примерно одинаковой производительности, за исключением использования файла ресурсов, который медленнее. Хотя Properties.Resources медленнее, он не сохраняется в исполняемом файле, поэтому в некоторых случаях он может быть более подходящим. Поэтому, на мой взгляд, используйте либо «статический класс», либо Properties.Resources, хранящие строки.

1 голос
/ 08 февраля 2010

Я думаю, что статика лучше, и вот мои рассуждения. Если этот код находится в некоторой библиотеке, и другой кусок кода использует эту библиотеку, если значение постоянных полей изменяется, то не только потребуется перекомпилировать эту библиотеку (дух), но вам придется перекомпилировать код, потребляющий библиотека также. Причиной этого является то, что компиляция вставляет постоянные значения, где бы вы ни ссылались на них. Однако, если вы используете static, у вас не будет этой проблемы, так как вы ссылаетесь на поле , а не на значение .

...