День двести тридцать четвёртый. #ЗаметкиНаПолях
Использование nameof
С точки зрения синтаксиса, оператор
Примеры использования
1. Валидация аргументов
При программировании по контракту каждый метод проверяет входящие данные. Это называется предусловиями. Например, далее используется статический метод класса
Предположим, что есть класс
Иногда атрибуты ссылаются на другие члены, чтобы обозначить, как члены связаны друг с другом. Это используется, например, в MVC DataAnnotations, где можно с помощью атрибутов обозначать ограничения, накладываемые на модель, например, требование обязательности поля, если поставлен флажок. NUnit позволяет параметризировать тесты значениями из поля или свойства, используя атрибут
1. Указание членов других типов
Стоит помнить, что
2. Обобщения
При использовании
Кроме того, тип параметра не выводится во время выполнения, а используется просто имя типа параметра. То есть для
3. Использование псевдонимов
При использовании псевдонимов
Оператор
Использование nameof
С точки зрения синтаксиса, оператор
nameof
похож на typeof
, за исключением того, что идентификатор в скобках не обязательно должен быть типом. Почему же лучше использовать nameof вместо строковых литералов? Это надёжнее. Если вы сделаете опечатку в строковом литерале, вам нечего укажет на неё, тогда как, если вы сделаете опечатку в имени операнда, вы получите ошибку во время компиляции. Кроме того, компилятор знает, что аргумент nameof связан с элементом или переменной. Если вы переименуете переменную, используя инструмент рефакторинга, имя аргумента тоже изменится. Однако заметьте, что компилятор по-прежнему не сможет определить проблему, если вы ссылаетесь на другой элемент с похожим именем.Примеры использования
1. Валидация аргументов
При программировании по контракту каждый метод проверяет входящие данные. Это называется предусловиями. Например, далее используется статический метод класса
Preconditions
для проверки аргумента на null
:public void SomeMethod(string name)2. Уведомление об изменении калькулируемого свойства
{
Preconditions.CheckNotNull(name, nameof(name));
…
}
Предположим, что есть класс
Rectangle
со свойствами Height
и Width
для чтения и записи и свойство только для чтения Area
. Полезно иметь возможность вызвать событие для свойства Area и указать имя свойства безопасным способом:public class Rectangle : INotifyPropertyChanged3. Атрибуты
{
public event PropertyChangedEventHandler PropertyChanged;
public double Width
{
get { … }
set
{
…
RaisePropertyChanged();
RaisePropertyChanged(nameof(Area));
}
}
…
}
Иногда атрибуты ссылаются на другие члены, чтобы обозначить, как члены связаны друг с другом. Это используется, например, в MVC DataAnnotations, где можно с помощью атрибутов обозначать ограничения, накладываемые на модель, например, требование обязательности поля, если поставлен флажок. NUnit позволяет параметризировать тесты значениями из поля или свойства, используя атрибут
TestCaseSource
. В Entity Framework достаточно распространено иметь в классе два свойства: одно для внешнего ключа, а другое - для сущности, которую представляет этот ключ:public class EmployeeОсобенности использования nameof
{
[ForeignKey(nameof(Employer))]
public Guid EmployerId { get; set; }
public Company Employer { get; set; }
}
1. Указание членов других типов
Стоит помнить, что
nameof
возвращает только имя члена, без имени класса. Например, nameof(Cultures.AllCultures)
вернёт "AllCultures
"2. Обобщения
При использовании
typeof
, и typeof(List<string>)
, и typeof(List<>)
допустимы и выдают разные результаты. При использовании nameof
, во-первых, нельзя использовать тип без аргумента типа nameof(List<>)
, а во-вторых, и nameof(Action<string>)
и nameof(Action<string, string>)
вернут просто "Action
".Кроме того, тип параметра не выводится во время выполнения, а используется просто имя типа параметра. То есть для
static string Method<T>() => nameof(T);И
Method<Guid>()
и Method<Button>()
вернут просто "T
".3. Использование псевдонимов
При использовании псевдонимов
nameof
также выводит имя псевдонима, а не обозначенного им типа. Следующий код выведет GuidAlias
, а не Guid
:using GuidAlias = System.Guid;4. Предопределённые псевдонимы, массивы и обнуляемые значимые типы
…
Console.WriteLine(nameof(GuidAlias));
Оператор
nameof
не может быть использован с предопределёнными псевдонимами (int
, char
, long
, и т.п.), с суффиксом ?
у обнуляемых типов или с массивами. То есть все следующие варианты не будут компилироваться: nameof(float)Источник: Jon Skeet “C# In Depth”. 4th ed – Manning Publications Co, 2019. Глава 9.
nameof(Guid?)
nameof(String[])