我已经实现了一个强类型的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);
}
}
答案 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>
通过类型推断,类型参数
int
和string
是 根据方法的论据确定。
答案 1 :(得分:2)
编译器可以自动从参数中推导出TValue
。实际上,调用行编译为:
this.NotifyPropertyUpdate<string>(x => x.Name);
当您调用几乎任何LINQ扩展方法时,您可以看到同样的事情发生。
答案 2 :(得分:1)
编译器推断出TValue
的类型。它仍然发生在编译时,而不是在运行时。
您传入以下lambda:x => x.Name
。编译器知道Name
的类型为string
,因此TValue
为string
。