为什么我必须使用“这个”?从扩展类中调用扩展方法?
我已经编写了数十种扩展方法,它们都按预期工作。但这是我第一次在这种情况下使用扩展方法。
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;
}
}
那为什么是“this.”呢?工作?
I've written dozens of extension methods and they all work as expected. But this is the first time I ran into using an extension method in this context.
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);
}
}
Looks normal enough, right? But within my controllers, I cannot access this extension method by typing. Instead, I have to prefix it with the keyword "this". For example:
// 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) ));
Very odd. Perhaps it is because I am within the instance object I am extending? The "controller" instance that is?
Sure enough, I was able to duplicate it in a simple console app:
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;
}
}
So why does 'this.' work?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
扩展方法不是成员“默认”查找的一部分 - 在检查扩展方法之前,您必须使用
Target.Method
形式的表达式。this.Foo()
符合该要求,因此它可以工作。来自第 7.5.5.2 节:
诚然,所有这些都说的是“编译器遵循规范”,而不是规范以这种方式编写的原因......我不知道是否有任何具体原因,尽管事实是您可以仅使用
Method()
(而不是指定实例或类型)来调用实例成员和静态成员可能是相关的。Extension methods aren't part of the "default" lookup for members - you have to be using an expression of the form
Target.Method
before extension methods are checked.this.Foo()
conforms to that requirement, so it works.From section 7.5.5.2:
Admittedly all that says is "the compiler is following the spec" rather than the reason why the spec was written that way... I don't know whether there is any specific reason, although the fact that you can invoke both instance members and static members using just
Method()
(instead of specifying either an instance or a type) may be relevant.我认为是因为扩展方法的工作原理。
当您编写 Go() 时,编译器假定 Go 是当前类中的方法,但事实并非如此。
扩展方法“附加”到实例,并且您可以使用 this 关键字指定实例。
I think is because of how extension methods works.
When you write Go(), the compiler assumes that Go is a method in the current class, which isn't.
Extension methods are 'attached' to a instance, and you specify the instance using the this keyword.