简体   繁体   English

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

[英]How to call an extension method from own class without casting?

I'm trying to call an extension method on my own class, but it fails to compile. 我试图在我自己的类上调用扩展方法 ,但它无法编译。 Consider the following lines of code: 请考虑以下代码行:

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();
    }
}

Basically I'm extending on the interface. 基本上我正在扩展界面。 I keep getting this error: 我一直收到这个错误:

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

Can anybody explains this to me? 有人可以向我解释一下吗? When I do a cast all seems well: 当我做一个演员表似乎很好:

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

Any explanations? 有什么解释吗?

The cast isn't necessary - the this part is. 演员阵容不是必需的 - this部分是。 So this works fine: 所以这很好用:

return this.HelloWorld();

Section 7.6.5.2 explicitly talks about method invocations of the form 第7.6.5.2节明确地讨论了表单的方法调用

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

This invocation: 这个调用:

HelloWorld()

isn't of that form, as there's no expression involved. 不是那种形式,因为没有表达。

It's not immediately clear to me why the language was designed that way (ie why the "implicit this" was excluded) and maybe Eric Lippert will add an answer to that effect later. 我不清楚为什么语言是这样设计的(即为什么“隐含的这个”被排除在外),也许Eric Lippert将在后面添加一个答案。 (The answer may well be along the lines of "because it would have taken a long time to spec, implement and test, for relatively little benefit.") However, this answer at least shows that the C# compiler is sticking to the spec... (答案很可能是“因为它需要花费很长时间才能进行规范,实现和测试,而且效益相对较小。”)但是,这个答案至少表明C#编译器坚持规范。 ..

this.HelloWorld(); works with no casting . 没有铸造工作

Remember how Extension methods work: 记住扩展方法的工作原理:

You use an object and compiler would know the type then it could resolve it to the extension method. 您使用一个对象,编译器会知道该类型,然后它可以将其解析为扩展方法。 If no object is used, then it would not be able to resolve it. 如果没有使用对象,那么它将无法解析它。

Not really an answer, but too long to fit in the comment section... 不是一个真正的答案,但是太长了,无法适应评论部分......

Let's take the following example, that I think is pretty common: 让我们来看下面的例子,我认为这很常见:

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

It is a perfectly valid point that the this is not necessary for the compiler to interpret the Select method properly. 这是一个非常正确的观点是, this是没有必要的编译器正确地解释选择方法。

However I think that in some ways, imposing the dot notation highlights the fact that we're dealing with an extension method, and that as such, the extension method will only access the members of the current instance through public accessors, even if you're calling it within the private scope of the class . 但是我认为在某些方面,强加点符号突出了我们正在处理扩展方法的事实,因此, 扩展方法只会通过公共访问器访问当前实例的成员,即使你'在类的私有范围内调用它

It makes explicit to the code reader that the extension method will treat the "this" instance as if it didn't know anything of its internal state. 它使代码阅读器明确表示扩展方法会将“this”实例视为不知道其内部状态的任何内容。 And indeed the class of the object is completely unknown to the extension method (as the extension method only knows the interface) 实际上,对象的类对于扩展方法是完全未知的(因为扩展方法只知道接口)

If the code was only: 如果代码只是:

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

it would be much less obvious that you're dealing with IEnumerable.Select that is actually calling the IList.GetEnumerator and getting every element one by one to call the x => x*x function. 你正在处理实际调用IList.GetEnumerator的IEnumerable.Select并逐个获取每个元素以调用x => x * x函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM