如何在不进行转换的情况下从自己的类调用扩展方法?

时间:2012-03-19 14:38:08

标签: c# .net c#-4.0 .net-4.0 extension-methods

我正在尝试在我自己的类上调用扩展方法,但它无法编译。请考虑以下代码行:

public interface IHelloWorld
{
}

public static class Extensions
{
    public static string HelloWorld(this IHelloWorld ext)
    {
        return "Hello world!";
    }
}

public class Test : IHelloWorld
{
    public string SaySomething()
    {
        return HelloWorld();
    }
}

基本上我正在扩展界面。我一直收到这个错误:

The name 'HelloWorld' does not exist in the current context

有人可以向我解释一下吗?当我做一个演员时,一切似乎都很好:

return ((Test)this).HelloWorld();

有任何解释吗?

3 个答案:

答案 0 :(得分:20)

cast 不是必需的 - this部分是。所以这很好用:

return this.HelloWorld();

第7.6.5.2节明确讨论了表单的方法调用

expr.identifier ( )
expr.identifier ( args )
expr.identifier < typeargs > ( )
expr.identifier < typeargs > ( args )

此调用:

HelloWorld()

不是那种形式,因为没有涉及表达。

我不能立即清楚为什么语言是这样设计的(即为什么“隐含此”被排除在外)并且Eric Lippert将在稍后添加该效果的答案。 (答案很可能是“因为它需要花费很长时间才能进行规范,实现和测试,而且效益相对较小。”)但是,这个答案至少表明C#编译器坚持规范。 ..

答案 1 :(得分:3)

this.HelloWorld();适用于无投放

记住扩展方法的工作原理:

您使用对象,编译器会知道该类型,然后它可以将其解析为扩展方法。如果没有使用任何对象,那么它将无法解决它。

答案 2 :(得分:1)

不是一个真正的答案,但是太长了,无法适应评论部分......

我们采取以下示例,我认为这很常见:

public class DoubleSet : List<double>
{
    public IEnumerable<double> Square()
    {
        return this.Select( x => x*x );
    }
}

完全有效的一点是编译器无需正确解释Select方法this

但是我认为在某些方面,强加点符号突出了我们正在处理扩展方法的事实,因此,扩展方法只会通过公共访问当前实例的成员访问者,即使你在类的私人范围内调用它

它向代码阅读器明确表示扩展方法会将“this”实例视为不知道其内部状态的任何内容。实际上,对象的类对于扩展方法是完全未知的(因为扩展方法只知道接口)

如果代码只是:

    public IEnumerable<double> Square()
    {
        return Select( x => x*x );
    }

你正在处理实际调用IList.GetEnumerator的IEnumerable.Select,并逐个获取每个元素来调用x =&gt; x * x函数。