为什么我必须使用“这个”从扩展类中调用扩展方法?

StackOverflow https://stackoverflow.com/questions/1616294

  •  06-07-2019
  •  | 
  •  

我已经编写了数十种扩展方法,它们都按预期工作。但这是我第一次在这种情况下使用扩展方法。

public static class ControllerExtensions
{
    public static RedirectToRouteResult RedirectToAction<TController>(
        this Controller controller
        , Expression<Action<TController>> action
      ) where TController : Controller
    {
      RouteValueDictionary routeValuesFromExpression = 
        ExpressionHelper.GetRouteValuesFromExpression<TController>(action);

      return new RedirectToRouteResult(routeValuesFromExpression);
    }
}

看起来很正常,对吗?但在我的控制器中,我无法通过键入来访问此扩展方法。相反,我必须在前面添加关键字“this”。例如:

// This does not work, I get a compiler error because
// RedirectToAction has no overload for the generic.
//
return
  RedirectToAction<MembershipController>(
     c => c.RegisterSuccess(Server.UrlEncode(code) ));

// But, this does work?!?!
//
return
  this.RedirectToAction<MembershipController>(
     c => c.RegisterSuccess(Server.UrlEncode(code) ));

很奇怪。也许是因为我在我正在扩展的实例对象中? “控制器”是指“控制器”。实例是什么?

果然,我能够在一个简单的控制台应用程序中复制它:

class Program
{
    static void Main(string[] args)
    {
        var x = new TestClass();
        x.Go<String>();
    }
}

public class TestClass
{
    public void Go()
    {
    }

    public void NextMethod()
    {
        // compiler error.  :(
        Go<String>();

        // works!
        this.Go<String>();
    }
}

public static class TestExtension
{
    public static string Go<T>(this TestClass theClass)
    {
        return String.Empty;
    }
}

为什么'这个'。工作?

有帮助吗?

解决方案

扩展方法不属于“默认”方法的一部分。查找成员 - 在检查扩展方法之前,您必须使用 Target.Method 形式的表达式。 this.Foo()符合该要求,因此可行。

从第7.5.5.2节:

  

在方法调用(&#167; 7.5.5.1)中   其中一种形式

expr . identifier ( )
expr . identifier ( args )
expr . identifier < typeargs > ( )
expr . identifier < typeargs > ( args ) if the normal processing of the
     

调用找不到适用的   方法,尝试处理   构造作为扩展方法   调用

不可否认,所有这些都是“编译器遵循规范”。而不是为什么规范是这样编写的...我不知道是否是否有任何特定原因,尽管你可以调用实例成员仅使用 Method()(而不是指定实例或类型)的静态成员可能是相关的。

其他提示

我认为是因为扩展方法的工作原理。

当你编写Go()时,编译器假定Go是当前类中的一个方法,而不是。

扩展方法“附加”到实例,并使用this关键字指定实例。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top