我已经编写了数十种扩展方法,它们都按预期工作。但这是我第一次在这种情况下使用扩展方法。
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;
}
}
为什么'这个'。工作?
答案 0 :(得分:5)
扩展方法不是成员“默认”查找的一部分 - 在检查扩展方法之前,您必须使用Target.Method
形式的表达式。 this.Foo()
符合该要求,因此可行。
从第7.5.5.2节:
在方法调用(第7.5.5.1节)中 其中一种形式
expr . identifier ( ) expr . identifier ( args ) expr . identifier < typeargs > ( ) expr . identifier < typeargs > ( args ) if the normal processing of the
调用找不到适用的 方法,尝试处理 构造作为扩展方法 调用
不可否认,所有这些都是“编译器遵循规范”,而不是规范编写的原因......我不知道是否是否有任何具体原因,尽管您可以仅使用Method()
调用实例成员和静态成员(而不是指定实例或类型)这一事实可能是相关的。
答案 1 :(得分:0)
我认为是因为扩展方法的工作原理。
当你编写Go()时,编译器假定Go是当前类中的一个方法,而不是。
扩展方法“附加”到实例,并使用this关键字指定实例。