2012-08-30 20 views
0

我已經實現了INotifyPropertyChanged的強類型實現,除了使用接口之外,我添加了一個基類來實現。爲什麼這個通用方法實現不需要傳遞Type值?

它工作正常,但我掙扎位就是爲什麼TValue在基本方法聲明中使用(我沒有使用這一部分從一些代碼,我在網上找到)

NotifyPropertyUpdate<TValue>( ...

但在派生類中,它根本不需要通過TValue

什麼告訴編譯器在運行時解決這個問題,而不是抱怨構建?

謝謝,

基類:

public class NotifyFuncPropertyChanged<T> : INotifyPropertyChanged 
{ 
    #region Implementation of INotifyPropertyChanged 

    public event PropertyChangedEventHandler PropertyChanged; 

    protected void NotifyPropertyUpdate<TValue>(Expression<Func<T, TValue>> selector) 
    { 
     //get memberInfo from object selection 
     MemberInfo memberInfoSelection; 
     Expression body = selector; 
     if (body is LambdaExpression) 
     { 
      body = ((LambdaExpression)body).Body; 
     } 
     switch (body.NodeType) 
     { 
      case ExpressionType.MemberAccess: 
       memberInfoSelection =((MemberExpression)body).Member; 
       break; 
      default: 
       throw new InvalidOperationException(); 
     } 

     //send notifyupdate to memberInfo 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(memberInfoSelection.Name)); 
     } 
    } 

    #endregion 
} 

用法(派生類)

public class NameTest : NotifyFuncPropertyChanged<NameTest> 
{ 
    public string Name { get; set; } 

    public void TestUpdateName() 
    { 
     this.NotifyPropertyUpdate(x => x.Name); 
    } 
} 

回答

3

C#編譯器有一個名爲的功能類型推斷。您可以在0123.的第7.5.2節中詳細瞭解它的所有複雜性,或者有一個非常簡短的介紹here

從規格:

當泛型方法被調用,而不指定類型參數,一個 類型推斷進程試圖推斷類型參數用於該呼叫。類型推斷的存在允許使用更方便的語法來調用通用方法,並允許程序員避免指定冗餘類型信息。例如,給定的 方法聲明:

class Chooser 
{ 
    static Random rand = new Random(); 
    public static T Choose<T>(T first, T second) { 
     return (rand.Next(2) == 0)? first: second; 
    } 
} 

能夠調用Choose方法而不明確 指定類型的參數:

int i = Chooser.Choose(5, 213);     // Calls Choose<int> 
string s = Chooser.Choose("foo", "bar");  // Calls Choose<string> 

通過類型推理,所述類型參數intstring是 由該方法的參數確定。

+1

很好的答案 - 謝謝。 –

1

編譯器推斷的TValue類型。它仍然發生在編譯時,而不是在運行時。

您傳入以下lambda:x => x.Name。編譯器知道Name類型爲string,因此TValuestring

+0

感謝您的回覆 - 但編譯器知道如何?是否在文字'TValue'上 - 如果我將其更改爲'TrainStation',會發生什麼? –

+1

泛型參數的名稱是不相關的。編譯器如何知道我在我的答案中解釋過。如果有什麼不清楚的地方,請詢問。 –

+0

我猜我沒有得到的是爲什麼編譯器在這種情況下協調TValue。是否因爲方法參數簽名是'Expression'類型?這又引發了一些問題,例如,當我還想將類型傳遞給基方法時會發生什麼。 (我剛剛嘗試了這一點,這意味着編譯器會停止推斷lambda類型) - 我只是發現它很混亂的行爲 –

2

編譯器可以自動從參數中推斷出TValue。實際上,呼叫線路編譯如下:

this.NotifyPropertyUpdate<string>(x => x.Name); 

你可以看到,當你調用幾乎任何LINQ擴展方法同樣的事情發生。

相關問題