为什么“;这个“;此处需要(扩展方法)

本文关键字:扩展 方法 这个 为什么 | 更新日期: 2023-09-27 17:58:54

元注释:不可能搜索单词"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. 为什么编译器不能弄清楚我正在寻找接受表达式的重载,并使用它?因为该方法采用一个操作的表达式,而不仅仅是一个操作,所以必须涉及该操作。我根本不了解Expressions命名空间,所以我不知道使用此参数类型的目的。

  2. 不管#1的答案是什么,为什么简单地添加this就能解决所有问题?

为什么“;这个“;此处需要(扩展方法)

扩展方法就是这样工作的。

根据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实例内部,如果不使用this.,就不能直接调用Print()。然而,我们可以很容易地进行test.Print()(或测试中的this.Print())。

我可以回答#2:您的类(this)只有一个RedirectToAction方法,所以没有歧义。我敢打赌,如果String过载,你会再次出现错误。

存在歧义。

当您使用'this'时,您会调用此方法-

Controller.RedirectToAction

如果没有"this",则调用扩展方法-

Microsoft.Web.Mvc.ControllerExtensions.RedirectToAction