среда, 12 октября 2016 г.

Получение имени метода вызвавшего текущий метод

В C# 6 появилось новое ключевое слово nameof которое позволяет получить строку с именем члена класса, что позволяет существенно упростить написание, например, реализации INotifyPropertyChanged. Зачем он нужен я писал вот здесь. Под катом, я покажу как упростить вызов метода OnPropertyChanged. Ну и покажу какой замечательный атрибут появился в .Net Framework 4.5 благодаря которому, даже nameof больше не нужно.

Итак, немного напомню. У нас есть некоторый класс реализующий упомянутый интерфейс. В интерфейсе объявлено всего одно событие и нам нужно при изменении значений свойств его вызывать. Такой класс может иметь вид:


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(thisnew 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([CallerMemberNamestring p_propertyName = "")
    {
        PropertyChanged?.Invoke(thisnew PropertyChangedEventArgs(p_propertyName));
    }
}

Стало намного лучше.

Комментариев нет:

Отправить комментарий