为什么这里需要“this”(扩展方法)?

时间:2011-06-08 20:26:07

标签: c# extension-methods this overload-resolution

元注:无法搜索“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作为第一个参数传递。

  1. 为什么编译器无法弄清楚我正在寻找带有Expression的重载,并使用它?因为该方法采用动作的表达式,而不仅仅是动作,必须参与其中。我根本不理解Expressions命名空间,所以我不知道使用这个参数类型的目的。

  2. 无论#1的答案是什么,为什么只添加this来解决所有问题?

3 个答案:

答案 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