Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在不强制转换的情况下从自己的类调用扩展方法?_C#_.net_C# 4.0_.net 4.0_Extension Methods - Fatal编程技术网

C# 如何在不强制转换的情况下从自己的类调用扩展方法?

C# 如何在不强制转换的情况下从自己的类调用扩展方法?,c#,.net,c#-4.0,.net-4.0,extension-methods,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 { publi

我试图在我自己的类上调用一个扩展方法,但它无法编译。考虑下面的代码行:

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
有人能给我解释一下吗?当我做演员时,一切似乎都很好:

返回((测试)this.HelloWorld()

有什么解释吗?

不需要演员阵容-这部分是。所以这很好:

return this.HelloWorld();
第7.6.5.2节明确讨论了表单的方法调用

expr.identifier ( )
expr.identifier ( args )
expr.identifier < typeargs > ( )
expr.identifier < typeargs > ( args )
不是那种形式,因为没有表情

我现在还不清楚为什么语言是这样设计的(也就是说,为什么“隐含的这个”被排除在外),也许Eric Lippert稍后会补充一个答案。(答案很可能是“因为规范、实现和测试可能需要很长时间,但好处相对较小。”)然而,这个答案至少表明C#编译器遵守规范。

this.HelloWorld()适用于无铸造

记住扩展方法是如何工作的:


您使用一个对象,编译器将知道该类型,然后它可以将其解析为扩展方法。如果没有使用对象,则无法解析它。

不是真正的答案,但太长,无法放入注释部分

让我们举一个我认为很常见的例子:

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

处理IEnumerable就不那么明显了。选择它实际上是调用IList.GetEnumerator并逐个获取每个元素来调用x=>x*x函数。

首先,我注意到如果您是编写调用站点
this.HelloWorld()的人
那么您就是可以将
HelloWorld
方法添加到当前类型的人。既然可以使用实例方法,为什么还要使用扩展方法呢?扩展方法的目的是使您能够向尚未拥有的类型添加方法。@EricLippert:我认为“向接口添加实用方法,该方法根据接口成员工作”的用例是第一种情况的一个轻微例外。我们并不(或者至少可能不)真的想在接口或实现中添加实例方法。如果我们可以将带有实体的实例方法添加到接口中(正如CLR团队的一位成员在一次访谈中所讨论的,可能是Vance Morrison?),那么调用该方法可能是完全合理的。扩展方法可以作为接口主体限制的一个不完善的解决方法。@EricLippert:第二点(关于LINQ)对于LINQ非常有意义。。。我想问题是,扩展方法的设计是否应该偏向于“刚好足以使LINQ工作”。当然,这可能就是成本/收益分析的用武之地。@Lippert:“扩展方法的意义在于使您能够将方法添加到您尚未拥有的类型中。”我有时使用扩展方法作为为接口方法添加通用默认实现的一种方式。因此,
IPlayer
声明
void-dedict()
(在其他方法中),
静态类PlayerRoutines
实现
void-dedict(这个IPlayer)
ChessPlayer:IPlayer
可以共享
dedict()
代码,即使这些类不共享一个共同的祖先。这是坏习惯吗?@Eric:有时候你会这么做。
public class DoubleSet : List<double>
{
    public IEnumerable<double> Square()
    {
        return this.Select( x => x*x );
    }
}
    public IEnumerable<double> Square()
    {
        return Select( x => x*x );
    }