C# 为什么这个泛型方法实现不需要传递类型值?
我已经实现了INotifyPropertyChanged的强类型实现,除了没有使用接口之外,我还添加了一个基类来实现 它工作得很好,但我正在努力解决的一点是为什么在基本方法声明中使用TValue(我确实使用了我在网上找到的一些代码中的这一部分)C# 为什么这个泛型方法实现不需要传递类型值?,c#,.net,linq,expression,C#,.net,Linq,Expression,我已经实现了INotifyPropertyChanged的强类型实现,除了没有使用接口之外,我还添加了一个基类来实现 它工作得很好,但我正在努力解决的一点是为什么在基本方法声明中使用TValue(我确实使用了我在网上找到的一些代码中的这一部分) NotifyPropertyUpdate( 但是在派生类中,它根本不需要传递TValue 是什么告诉编译器在运行时解决这个问题,而不是在构建时抱怨 谢谢 基类: public class NotifyFuncPropertyChanged<T>
NotifyPropertyUpdate(
但是在派生类中,它根本不需要传递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
}
公共类NotifyFuncPropertyChanged:INotifyPropertyChanged
{
#INotifyPropertyChanged的区域实现
公共事件属性更改事件处理程序属性更改;
受保护的void NotifyPropertyUpdate(表达式选择器)
{
//从对象选择中获取memberInfo
MemberInfo memberInfoSelection;
表达式体=选择器;
if(主体为LambdaExpression)
{
body=((LambdaExpression)body.body;
}
开关(body.NodeType)
{
case ExpressionType.MemberAccess:
memberInfoSelection=((MemberExpression)body.Member;
打破
违约:
抛出新的InvalidOperationException();
}
//向memberInfo发送notifyupdate
if(PropertyChanged!=null)
{
PropertyChanged(这是新的PropertyChangedEventArgs(memberInfoSelection.Name));
}
}
#端区
}
用法(派生类)
公共类名称测试:NotifyFuncPropertyChanged
{
公共字符串名称{get;set;}
public void TestUpdateName()
{
this.NotifyPropertyUpdate(x=>x.Name);
}
}
编译器推断TValue的类型。它仍然发生在编译时,而不是运行时
您传入以下lambda:x=>x.Name
。编译器知道Name
是string
类型,因此TValue
是string
编译器推断TValue
的类型。它仍然发生在编译时,而不是运行时
传入以下lambda:x=>x.Name
。编译器知道Name
是string
类型,因此TValue
是string
编译器可以从参数自动推断TValue
。实际上,调用行编译为:
this.NotifyPropertyUpdate<string>(x => x.Name);
this.NotifyPropertyUpdate(x=>x.Name);
当您调用几乎所有LINQ扩展方法时,都可以看到同样的情况发生。编译器可以自动从参数中推断出TValue
。实际上,调用行编译为:
this.NotifyPropertyUpdate<string>(x => x.Name);
this.NotifyPropertyUpdate(x=>x.Name);
当你调用几乎所有的LINQ扩展方法时,你都会看到同样的事情发生。C#编译器有一个名为类型推断的功能。你可以在第7.5.2节中了解它的复杂性,或者有一个非常简单的介绍
根据规范:
当在不指定类型参数的情况下调用泛型方法时
类型推断进程尝试推断调用的类型参数。类型推断的存在允许更方便的语法
用于调用泛型方法,并允许程序员
避免指定冗余类型信息。例如,给定
方法声明:
class Chooser
{
static Random rand = new Random();
public static T Choose<T>(T first, T second) {
return (rand.Next(2) == 0)? first: second;
}
}
通过类型推断,类型参数int
和string
是
根据方法的参数确定
C#编译器有一个名为类型推断的功能。您可以在第7.5.2节中了解它的所有复杂性,或者有一个非常简单的介绍
根据规范:
当在不指定类型参数的情况下调用泛型方法时
类型推断进程尝试推断调用的类型参数。类型推断的存在允许更方便的语法
用于调用泛型方法,并允许程序员
避免指定冗余类型信息。例如,给定
方法声明:
class Chooser
{
static Random rand = new Random();
public static T Choose<T>(T first, T second) {
return (rand.Next(2) == 0)? first: second;
}
}
通过类型推断,类型参数int
和string
是
根据方法的参数确定
谢谢你的回答-但是编译器怎么知道?是在类型文本“TValue”上吗?如果我将其更改为“TrainStation”,会发生什么?泛型参数的名称是不相关的。编译器怎么知道我在我的回答中解释的。如果有什么不清楚的,请询问。我想我没有得到的是为什么编译器在这个sc中协调TValue是因为方法参数签名的类型为“Expression”吗?这再次引发了一些问题,例如,当我还想将类型传递给基方法时会发生什么情况。(我刚刚尝试过这个,这意味着编译器停止推断lambda类型)-我只是觉得很困惑behavior@Patrick:编译器将始终尝试推断任何泛型方法上的所有泛型类型参数,而不考虑参数类型。没有“魔术标记”涉及。相反,您始终可以选择重写此选项,并在调用站点显式指定泛型类型。感谢您的回答-但编译器如何知道?它是否位于类型文本“TValue”上?如果我将其更改为“TrainStation”,会发生什么情况?泛型参数的名称与此无关。编译器如何知道我已解释过在我的回答中。如果有什么不清楚的地方,请提问。我想我没有得到的是为什么编译器会在这种情况下协调TValue。是因为方法参数签名的类型是“Expression”吗?这再次引发了一些问题,例如,当我还想将类型传递给基方法时会发生什么。(我有