代码之家  ›  专栏  ›  技术社区  ›  M4N

为什么从扩展类中调用扩展方法需要'this'关键字

  •  74
  • M4N  · 技术社区  · 14 年前

    public static class ViewExtensions
    {
        public static string Method<T>(this ViewPage<T> page) where T : class
        {
            return "something";
        }
    }
    

    从视图调用此方法时(从 ViewPage ),我得到错误“ “除非我用 this

    <%: Method() %> <!-- gives error CS0103 -->
    <%: this.Method() %> <!-- works -->
    

    为什么 是否需要关键字?或者没有它也行,但我错过了什么?

    (我想这个问题一定有重复的,但我找不到)

    更新 :

    Ben Robinson says ,调用扩展方法的语法就是编译糖。那么为什么编译器不能在不需要this关键字的情况下自动检查当前类型的基类型的扩展方法呢?

    6 回复  |  直到 7 年前
        1
  •  56
  •   Eric Lippert    14 年前

    有两点:

    首先,建议的特性(在扩展方法调用上隐式的“this.”)是 . 扩展方法是LINQ查询理解按我们所希望的方式工作所必需的;接收者总是在查询中声明的,因此不必支持隐式方法来使LINQ工作。

    反对 允许您扩展自己无法扩展的类型 ,或者是因为它是一个接口而您不知道实现,或者是因为您知道实现但没有源代码。

    那你呢 有权访问源代码。 那你为什么要用扩展方法呢? 如果您可以访问扩展类型的源代码,那么您就完全不必使用扩展方法了!然后,您的实现可以利用对对象私有状态的访问,而扩展方法不能。

    考虑到这两点,语言设计者就不再有责任解释这个特性为什么会这样做 应该 . 功能具有与之相关的巨大成本。这个特性是不必要的,并且违背了扩展方法的既定设计目标;为什么我们要承担实现它的成本?解释这个特性支持了什么引人注目的重要场景,我们将在将来考虑实现它。我没有看到任何令人信服的,重要的场景来证明这一点,但也许有一个我错过了。

        2
  •  9
  •   Ferruccio bayda    14 年前

    如果没有它,编译器只会将其视为静态类中的静态方法,该静态类将page作为其第一个参数。即

    // without 'this'
    string s = ViewExtensions.Method(page);
    

    与。

    // with 'this'
    string s = page.Method();
    
        3
  •  6
  •   Alex Humphrey    14 年前

    在实例方法上,“this”以透明方式隐式传递给每个方法,因此您可以访问它提供的所有成员。

    Method() 而不是 this.Method() Method(this) ,您没有告诉编译器要传递给该方法的内容。

    您可能会说“为什么它不知道调用对象是什么,并将其作为参数传递?”

    答案是扩展方法是静态的,可以从没有“this”的静态上下文调用。

    我想他们可以在编译过程中检查一下,但老实说,这可能需要大量的工作才能获得极少的回报。老实说,我认为去掉一些扩展方法调用的明确性并没有什么好处。它们可能被误认为是实例方法,这意味着它们有时可能非常不直观(例如,没有抛出NullReferenceExceptions)。我有时认为他们应该为扩展方法引入一个新的“pipeforward”类型的操作符。

        4
  •  3
  •   stakx - no longer contributing Saravana Kumar    14 年前

    需要注意的是

    我将给出另一个不同之处的示例:在 null

    static void ExtensionMethod(this object obj) { ... }
    
    object nullObj = null;
    nullObj.ExtensionMethod();  // will succeed without a NullReferenceException!
    

    尽管如此,我同意这似乎有点不合逻辑 this 调用扩展方法时需要。毕竟,一个扩展方法在理想情况下应该是“感觉”的,并且表现得和普通方法一样。

        5
  •  1
  •   Coding Flow    14 年前

    因为ViewPage类不存在扩展方法。你需要告诉编译器你在调用什么扩展方法。记得 this.Method() 只是糖而已 ViewExtensions.Method(this)

        6
  •  1
  •   Reyn    7 年前