4

元注释:不可能搜索“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解决所有问题?

4

3 回答 3

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()在 Test 内部)。

于 2011-06-08T20:44:08.793 回答
0

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

于 2011-06-08T20:29:25.480 回答
0

有歧义。

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

Controller.RedirectToAction

如果没有“this”,您将调用扩展方法 -

Microsoft.Web.Mvc.ControllerExtensions.RedirectToAction
于 2011-06-08T20:33:47.467 回答