Chapter 1 - Item 6 : Avoid String-ly Typed APIS

Effective C# (Covers C# 6.0), (includes Content Update Program): 50 Specific Ways to Improve Your C#, 3rd Edition By Bill Wagner 讀後心得

字串常被當作鍵值做比對,雖然方便但也失去了靜態型別的優勢與安全性。 Item 6 提出一個自 C# 6.0 開始支援的語法 nameof 以取得變數的名稱,避免 hard code 字串比較。

範例程式碼:

今天有一個類別 User,類別中定義了 Name 與 Address;該類別實作 INotifyPropertyChanged 用以通知 Client 更新 UI 畫面。

public class User : INotifyPropertyChanged
{
    private string _address;

    private string _name;

    public string Address
    {
        get { return _address; }
        set
        {
            _address = value;
            PropertyChanged?.Invoke( this, 
                new PropertyChangedEventArgs( "Address" ) ) );
        }
    }

    public string Name
    {
        get { return _name; }
        set
        {
            _name = value;
            PropertyChanged?.Invoke( this, 
                new PropertyChangedEventArgs( "Name" ) );
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

Client:

User _user = new User( );
this.textBox1.DataBindings.Add( "Text", _user, "Name", false, DataSourceUpdateMode.OnPropertyChanged );
this.textBox2.DataBindings.Add( "Text", _user, "Address", false, DataSourceUpdateMode.OnPropertyChanged );

從客戶端程式碼中發現,在做 DataBindings 時需帶入 "Name" 與 "Address";這代表日後若改變了 User 中 Name 或 Address 屬性的命名,除了 User 類別 PropertyChanged 參數需要修改,用戶端的程式碼也必須跟著修改(易產生錯誤)。

使用 nameof 重構程式。

public class User : INotifyPropertyChanged
{
    private string _address;

    private string _name;

    public string Address
    {
        get { return _address; }
        set
        {
            _address = value;
            PropertyChanged?.Invoke( this, 
                new PropertyChangedEventArgs( nameof( Address ) ) );
        }
    }

    public string Name
    {
        get { return _name; }
        set
        {
            _name = value;
            PropertyChanged?.Invoke( this, 
                new PropertyChangedEventArgs( nameof( Name ) ) );
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

User _user = new User( );
this.textBox1.DataBindings.Add( "Text", _user, nameof( _user.Name ), false, DataSourceUpdateMode.OnPropertyChanged );
this.textBox2.DataBindings.Add( "Text", _user, nameof( _user.Address ), false, DataSourceUpdateMode.OnPropertyChanged );

修改後的版本發現帶入的參數不再是 hard code 的字串;而是隨著屬性名稱變動,減少錯誤發生機會也省去修改 User 類別中 PropertyChanged 參數及客戶端程式碼的工夫。

結論:
1. 使用 nameof 修飾字避免修改命名後造成的不匹配錯誤。

2. 實務上應該避免直接用字串做比對,盡量使用更明確的定義做比對(e.g. enum)。