Объявление констант с помощью nameof() константы в качестве значения
сценарий
У меня есть класс для объявления string
константы, используемые вокруг программы:
public static class StringConstants
{
public const string ConstantA = "ConstantA";
public const string ConstantB = "ConstantB";
// ...
}
По сути, не имеет значения, каково действительное значение константы, так как оно используется при назначении и использовании. Это просто для проверки.
Имена констант будут довольно понятны, но я хочу попытаться избежать использования одних и тех же строковых значений более одного раза.
Что я хотел бы сделать
я знаю это nameof()
оценивается во время компиляции, поэтому вполне возможно назначить const string
ценность для nameof()
член.
Чтобы не писать эти магические строки, я подумал об использовании nameof()
сама константа.
Вот так:
public static class StringConstants
{
public const string ConstantA = nameof(ConstantA);
public const string ConstantB = nameof(ConstantB);
// ...
}
Вопрос...
Я думаю, что нет реальной пользы от использования nameof()
кроме рефакторинга?
Есть ли какие-либо последствия для использования nameof()
при назначении констант?
Должен ли я придерживаться только жестко закодированной строки?
3 ответа
Хотя я думаю, что использование nameof
это умно, я могу вспомнить несколько сценариев, где это может вызвать проблемы (не все из них могут относиться к вам):
1 / Есть некоторые строковые значения, для которых вы не можете иметь одинаковые имя и значение. Например, любое строковое значение, начинающееся с числа, не может использоваться в качестве имени константы. Таким образом, у вас будут исключения, когда вы не сможете использовать nameof
,
2/ В зависимости от того, как используются эти значения (например, если они являются именами значений, хранящихся в базе данных, в XML-файле и т. Д.), Вы не можете изменять значения - это нормально, пока вы не придете к рефакторингу, Если вы хотите переименовать константу, чтобы сделать ее более читабельной (или исправить орфографическую ошибку предыдущего разработчика), вы не сможете изменить ее, если используете nameof
,
3/ Для других разработчиков, которым необходимо поддерживать ваш код, подумайте, какой из них более читабелен:
public const string ConstantA = nameof(ContantA);
или же
public const string ConstantA = "ConstantA";
Лично я думаю, что это последнее. На мой взгляд, если вы идете nameof
Тогда это может дать другим разработчикам повод остановиться и задуматься, почему вы так поступили. Это также подразумевает, что важно имя константы, тогда как если ваш сценарий использования не похож на мой, то значение имеет значение, и имя для удобства.
Если вы принимаете, что бывают случаи, когда вы не можете использовать nameof
Тогда есть ли реальная польза от его использования? Я не вижу никаких недостатков, кроме вышеперечисленного. Лично я бы рекомендовал придерживаться традиционных жестко закодированных строковых констант.
Тем не менее, если ваша цель состоит в том, чтобы просто убедиться, что вы не используете одно и то же строковое значение более одного раза, то (поскольку это приведет к ошибке компиляции, если два имени совпадают), это будет очень эффективным решением.
Использование оператора с общедоступными константными строками рискованно. Как следует из названия, значение общедоступной константы должно быть действительно постоянным/постоянным . Если у вас есть общедоступная константа, объявленная с помощьюnameof()
и если вы переименуете его позже, вы можете сломать свой клиентский код, используя константу. В своей книге Essential C# 4.0 Марк Михаэлис отмечает: (выделено мной)
общедоступные константы должны быть постоянными, потому что изменение их значения не обязательно вступит в силу в сборках, которые его используют. Если сборка ссылается на константы из другой сборки, значение константы компилируется непосредственно в ссылающуюся сборку. Таким образом, если значение в ссылочной сборке изменено, но ссылочная сборка не перекомпилирована, ссылочная сборка по-прежнему будет использовать исходное значение, а не новое значение. Значения, которые потенциально могут измениться в будущем, должны быть указаны как доступные только для чтения .
Я думаюnameof()
имеет 2 преимущества перед литеральными строками:
1.) При изменении имени вы получите ошибки компилятора, если не измените все вхождения. Так что это менее подвержено ошибкам.
2.) При быстрой попытке понять код, который вы не написали сами, вы можете четко различить, из какого контекста происходит это имя. Пример:
ViewModel1.PropertyChanged += OnPropertyChanged; // add the event handler in line 50
...
void OnPropertyChanged(object sender, string propertyName) // event handler in line 600
{
if (propertyName == nameof(ViewModel1.Color))
{
// no need to scroll up to line 50 in order to see
// that we're dealing with ViewModel1's properties
...
}
}