В C# 6 появилось новое ключевое слово nameof которое позволяет получить строку с именем члена класса, что позволяет существенно упростить написание, например, реализации INotifyPropertyChanged. Зачем он нужен я писал вот здесь. Под катом, я покажу как упростить вызов метода OnPropertyChanged. Ну и покажу какой замечательный атрибут появился в .Net Framework 4.5 благодаря которому, даже nameof больше не нужно.
Итак, немного напомню. У нас есть некоторый класс реализующий упомянутый интерфейс. В интерфейсе объявлено всего одно событие и нам нужно при изменении значений свойств его вызывать. Такой класс может иметь вид:
Как видно, при вызове метода OnProeprtyChanged мы вынуждены передавать строку. Что может привести к тому, что свойство мы переименуем, через рефакторинг изменение распространиться везде кроме этой строки и об изменении свойства никто не узнает.
Решить эту проблему можно применением нового ключевого слова nameof , вот так:
Но и это еще не все. С появлением атрибута [CallerMemberName], у нас есть возможность вообще ничего не передавать в этот метод, он сам будет узнавать имя члена класса который его вызвал:
Стало намного лучше.
Итак, немного напомню. У нас есть некоторый класс реализующий упомянутый интерфейс. В интерфейсе объявлено всего одно событие и нам нужно при изменении значений свойств его вызывать. Такой класс может иметь вид:
public class MyClass : INotifyPropertyChanged { private string _myString; public string MyString { get { return _myString; } set { if (value != _myString) { _myString = value; OnPropertyChanged(nameof(MyString)); } } } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string p_propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(p_propertyName)); } }
Как видно, при вызове метода OnProeprtyChanged мы вынуждены передавать строку. Что может привести к тому, что свойство мы переименуем, через рефакторинг изменение распространиться везде кроме этой строки и об изменении свойства никто не узнает.
Решить эту проблему можно применением нового ключевого слова nameof , вот так:
public string MyString
{
get
{
return _myString;
}
set
{
if (value != _myString)
{
_myString = value;
OnPropertyChanged(nameof(MyString));
}
}
}
Но и это еще не все. С появлением атрибута [CallerMemberName], у нас есть возможность вообще ничего не передавать в этот метод, он сам будет узнавать имя члена класса который его вызвал:
public class MyClass : INotifyPropertyChanged
{
private string _myString;
public string MyString
{
get
{
return _myString;
}
set
{
if (value != _myString)
{
_myString = value;
OnPropertyChanged();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string p_propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(p_propertyName));
}
}
Стало намного лучше.
на сколько такой вызов быстрее?
ОтветитьУдалитьnameof() это всё же константа, доступ к которой как я понимаю будет быстрее.
Как всегда за все надо платить. Пишем nameof платим лишним стучанием по клавиатуре и большей скоростью работы, используем CallerMemberName меньше стучим по клавиатуре, чуть медленнее происходит вызов. Насколько медленнее не замерял, но в приложениях в которых у вас каждую секунду в интерфейсе не меняются тысячи полей... У меня есть подозрение что сложно будет заметить изменение производительности.
Удалить