Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/spring-mvc/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么这个泛型方法实现不需要传递类型值?_C#_.net_Linq_Expression - Fatal编程技术网

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

C# 为什么这个泛型方法实现不需要传递类型值?,c#,.net,linq,expression,C#,.net,Linq,Expression,我已经实现了INotifyPropertyChanged的强类型实现,除了没有使用接口之外,我还添加了一个基类来实现 它工作得很好,但我正在努力解决的一点是为什么在基本方法声明中使用TValue(我确实使用了我在网上找到的一些代码中的这一部分) NotifyPropertyUpdate( 但是在派生类中,它根本不需要传递TValue 是什么告诉编译器在运行时解决这个问题,而不是在构建时抱怨 谢谢 基类: public class NotifyFuncPropertyChanged<T>

我已经实现了INotifyPropertyChanged的强类型实现,除了没有使用接口之外,我还添加了一个基类来实现

它工作得很好,但我正在努力解决的一点是为什么在基本方法声明中使用TValue(我确实使用了我在网上找到的一些代码中的这一部分)

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”吗?这再次引发了一些问题,例如,当我还想将类型传递给基方法时会发生什么。(我有