Подтвердить что ты не робот

С# Статический класс vs struct для предопределенных строк

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

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);
}

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

Ответ 3

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

Ответ 4

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

У констант есть несколько недостатков:

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

Я бы написал ваш код, как это (обратите внимание на переименование рефакторинга тоже):

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";
}

Ответ 5

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

Ответ 6

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

Ответ 7

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

Ответ 8

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

Ответ 9

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

Вот результаты моего быстрого теста, который включает в себя длину, сравнение, concat, copy, indexOf и Substring. Он запускался под версией .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 работает медленнее, он не сохраняется в исполняемом файле, поэтому в некоторых случаях это может быть более уместным. Поэтому используйте, по моему мнению, "статический класс" или "Свойства". Источники хранения сохраняют строки.

Ответ 10

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

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

Ответ 11

В моей практике для этой цели мы используем Dictionary<enumNameType, string>. Где enumNameType - это другой тип имен, который вы можете иметь (в вашем случае)... Этот словарь завернут в статический класс и кэшируется - мы создаем его только в первый раз, когда мы его используем, а затем возвращаем тот же объект...

Я надеюсь, что это тоже будет полезно для вас!

Ответ 12

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

Ответ 13

Простым фактом, что вам разрешено создавать новый объект, который предназначен для постоянного, является явным доказательством плохой практики (обычно). Я говорю "обычно", потому что .NET иногда использует концепцию, хотя непонятно, почему.

Конечно, вы всегда можете делать такие вещи:

public class Foo
{
    public struct Bar
    {
        public static double A = 100;

        public Bar(double a)
        {
            A = a;
        }
    }
}

Что технически оправдывает создание Bar; тем не менее, нет никакой гарантии, что константа Bar будет всегда одинаковой (даже в однопоточной среде) и в конечном итоге мало используется.