Почему здесь "this" требуется (метод расширения)? - PullRequest
4 голосов
/ 09 июня 2011

Мета-примечание: невозможно найти слово «это».

Я только что натолкнулся на странный сценарий в 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 исправляет все?

Ответы [ 3 ]

4 голосов
/ 09 июня 2011

Методы расширения работают таким образом.

Согласно спецификации 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).

0 голосов
/ 09 июня 2011

Существует двусмысленность.

Когда вы используете 'this' , вы вызываете этот метод -

Controller.RedirectToAction

Без 'this' васвызвать метод расширения -

Microsoft.Web.Mvc.ControllerExtensions.RedirectToAction
0 голосов
/ 09 июня 2011

Я могу ответить # 2: В вашем классе (this) есть только один метод RedirectToAction, поэтому двусмысленности нет.Бьюсь об заклад, если вы перегрузите String тот, вы получите эту ошибку снова.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...