为什么这个泛型方法实现不需要传递Type值?

时间:2012-08-30 11:27:22

标签: c# .net linq expression

我已经实现了一个强类型的INotifyPropertyChanged实现,除了使用该接口,我添加了一个基类来实现。

它工作正常,但我正在努力解决的问题是为什么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 个答案:

答案 0 :(得分:3)

C#编译器有一个名为类型推断的功能。您可以在the language specification的第7.5.2节中详细了解它,或者有一个非常简短的介绍here

来自规范:

  

当调用泛型方法而不指定类型参数时,a   类型推断进程尝试推断调用的类型参数。类型推断的存在允许更方便的语法   用于调用泛型方法,并允许程序员   避免指定冗余类型信息。例如,给定   方法声明:

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 :(得分:2)

编译器可以自动从参数中推导出TValue。实际上,调用行编译为:

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

当您调用几乎任何LINQ扩展方法时,您可以看到同样的事情发生。

答案 2 :(得分:1)

编译器推断出TValue的类型。它仍然发生在编译时,而不是在运行时。

您传入以下lambda:x => x.Name。编译器知道Name的类型为string,因此TValuestring