4
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例如在初始化字段时。

4

3 回答 3

3

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

yourClass.ExtensionMethod()不一样yourClass.ClassMethod()

基本上,您正在做的是获得一种方便的方法:

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

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

于 2012-10-17T07:02:58.603 回答
2

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

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

于 2012-10-17T07:12:49.580 回答
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这样的人注意,当他们决定该要求时,他们可能在哪里

于 2012-10-18T09:06:38.680 回答