我正在尝试在我自己的类上调用扩展方法,但它无法编译。请考虑以下代码行:
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();
有任何解释吗?
答案 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函数。