元注:无法搜索“this”这个词。
我刚刚在ASP.NET中遇到一个需要this
关键字的奇怪场景。但它不是为了解析本地变量和实例变量,正如您在构造函数中看到的那样。
Microsoft.Web.Mvc包含一个名为ControllerExtensions
的类,我正在使用RedirectToAction(Expression<Action<TController>> action)
重载。也许这很特别,因为重载是一个扩展。
RedirectToAction(c => c.Index())
无法编译,它会显示Cannot convert lambda expression to type 'string' because it is not a delegate type
。现在这听起来像我认为我正在使用带有字符串的第一个重载。
this.RedirectToAction(c => c.Index())
编译好。我也可以静态调用它,将this
作为第一个参数传递。
为什么编译器无法弄清楚我正在寻找带有Expression的重载,并使用它?因为该方法采用动作的表达式,而不仅仅是动作,必须参与其中。我根本不理解Expressions命名空间,所以我不知道使用这个参数类型的目的。
无论#1的答案是什么,为什么只添加this
来解决所有问题?
答案 0 :(得分:4)
扩展方法以这种方式工作。
根据C#规范(7.6.5.2 Extension method invocations
),只有在呼叫具有“其中一种形式”时才使用扩展方法:
expr . identifier ( )
expr . identifier ( args )
expr . identifier < typeargs > ( )
expr . identifier < typeargs > ( args )
这基本上意味着你总是必须在“。”的左边有一些东西。让编译器解析扩展方法。 expr.
部分必须存在(而不是dynamic
),以便编译器查找扩展方法。
例如,这是一个小测试,演示:
namespace TestNamespace
{
using System;
public static class TextExtension
{
public static void Print(this Test test)
{
Console.WriteLine("Found");
}
}
public class Test
{
public void Foo()
{
// Compiler error!
Print();
// Works fine
this.Print();
}
static void Main()
{
Test test = new Test();
test.Foo();
// Fine here
test.Print();
Console.ReadKey();
}
}
}
请注意编译器错误 - 因为我们在Test实例中,所以在不使用Print()
的情况下无法直接调用this.
。但是,我们可以轻松地在测试中test.Print()
(或this.Print()
)。
答案 1 :(得分:0)
我可以回答#2:你的班级(this
)只有一个RedirectToAction方法,所以没有歧义。我敢打赌,如果你重载了String
,你会再次遇到错误。
答案 2 :(得分:0)
存在歧义。
当您使用'this'时,您将调用此方法 -
Controller.RedirectToAction
如果没有'this',你可以调用extennsion方法 -
Microsoft.Web.Mvc.ControllerExtensions.RedirectToAction