为什么在从扩展类的方法中调用扩展方法时,我们必须显式指定“this”?

时间:2012-10-17 06:51:22

标签: c# .net this extension-methods

public class StoreController : Controller
{
    public string Index()
    {
        // implicitly specified instance does not work
        //return GetMemberName();

        // must specify this explicitly
        return this.GetMemberName();
    }
}

public static class Utilities
{
    public static string GetMemberName(this Controller caller,
        [CallerMemberName] string memberName = "")
    {
        return caller.GetType().FullName + "." + memberName;
    }
}

为什么在从扩展类的方法中调用扩展方法时,我们必须显式指定this

在我的心理模型中,我们通常可以省略this,例如我们初始化字段时。例如。

3 个答案:

答案 0 :(得分:3)

扩展方法在技术上不是附加到您的类的方法。

yourClass.ExtensionMethod()yourClass.ClassMethod()不同。

基本上,你正在做的是方便地做到这一点:

ExtensionMethod(YourClass yourClass) {
    //do something
    return yourClass;
}

这是我对扩展方法的理解。对于无法更改的类调用方法,这是一种方便的方法。所以,这就是为什么你不能在没有this.的情况下调用它。它不是类方法。

答案 1 :(得分:2)

扩展方法只是一种调用静态方法的语法糖。这段代码return this.GetMemberName();实际上转换为对Utilities.GetMemberName(this);

等静态方法的调用

如您所见,您必须将this发送到静态方法,这就是您需要this个关键字的原因。

答案 2 :(得分:1)

没有参加设计委员会的决定,很难说这就是为什么。

在本文中,我使用与特定对象实例相关联的函数意义上的方法或实例方法,并且我在数学意义上使用函数。函数接收许多参数并创建结果(可能无效)

如果我们不考虑更复杂的虚方法,因为要调用的实际函数是运行时确定的,那么任何和所有方法调用都是语法糖。如果我们在下面定义了两种方法

internal static class Extensions {
  public static string FooEx(this MyClass self){
     return self.ToString();
  }
}

internal class MyClass {
  public string Bar(){
     var s1 = Foo();
     var s2 = this.FooEx();
  }

  private string Foo(){
      return ToString();
  }
}

然后两者都将被转换为函数调用,其中两个个案中的第一个(也是唯一的)参数将是this标识的对象。如果您对此有疑问,那么请查看为实例方法调用而生成的IL,您会注意到与代码中的声明相比有一个额外的参数。此参数是this引用,始终作为实例方法的第一个参数传递。

因此,在实例方法的情况下,编译器仍然需要确定要传递哪个对象作为函数的第一个参数。如果你在没有this的情况下调用扩展方法,那就完全一样,这也意味着这不是你必须使用this的真正原因在扩展方法面前。

Marvin的编译器中,构建在Mono编译器之上的编译器我必须做与C#类似的技巧和扩展方法,并且想知道为什么规范需要this 编译器强制您在扩展方法之前使用this的真正原因是规范是这样说的。这个决定背后的原因是什么需要像@EricLippert这样的人注意,他们可能在那里决定了这个要求