C# Статический класс по сравнению со структурой для предопределенных строк

Коллега просто создал следующую конструкцию в 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);
}

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

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

49
задан Rob van Groenewoud 8 February 2010 в 06:41
поделиться

10 ответов

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

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

44
ответ дан 7 November 2019 в 11:25
поделиться

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

0
ответ дан 7 November 2019 в 11:25
поделиться

Можно попробовать многопоточность. Класс таймера: http://docs.python.org/library/threading.html#timer-objects .

import threading

def f(f_stop):
    # do something here ...
    if not f_stop.is_set():
        # call f() again in 60 seconds
        threading.Timer(60, f, [f_stop]).start()

f_stop = threading.Event()
# start calling f now and every 60 sec thereafter
f(f_stop)

# stop the thread when needed
#f_stop.set()
-121--1008227-

Я думаю, что TDD и функциональное программирование (FP) отличаются тем, что TDD является методологией, а FP является парадигмой программирования.

Я бы сказал, что FP помогает при практике TDD в качестве FP призывает вас сделать вещи детерминированными, когда это возможно. Детерминированные функции гораздо легче проверить, чем недетерминированные.

-121--4090498-

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

Надеюсь, вам это тоже пригодится!

0
ответ дан 7 November 2019 в 11:25
поделиться

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

5
ответ дан 7 November 2019 в 11:25
поделиться

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

1
ответ дан 7 November 2019 в 11:25
поделиться

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

6
ответ дан 7 November 2019 в 11:25
поделиться

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

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

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

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

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";
}
11
ответ дан 7 November 2019 в 11:25
поделиться

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

25
ответ дан 7 November 2019 в 11:25
поделиться

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

31
ответ дан 7 November 2019 в 11:25
поделиться

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

5
ответ дан 7 November 2019 в 11:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: