Почему вы не можете напрямую вызывать методы расширения? - PullRequest
10 голосов
/ 11 октября 2010

Может кто-нибудь объяснить мне, почему в следующем 3-м вызов DoSomething недействителен?(Сообщение об ошибке «Имя DoSomething не существует в текущем контексте»)

public class A { }
public class B : A
{
    public void WhyNotDirect()
    {
        var a = new A();
        a.DoSomething();  // OK
        this.DoSomething();  // OK
        DoSomething(); // ?? Why Not
    }
}
public static class A_Ext
{
    public static void DoSomething(this A a)
    {
        Console.WriteLine("OK");
    }
}

Ответы [ 4 ]

5 голосов
/ 11 октября 2010

Методы расширения могут быть вызваны как другие статические методы.

Измените его на A_Ext.DoSomething(this).

Если вы спрашиваете, почему он не вызывается неявнона this ответ таков: спецификация была написана так.Я предполагаю, что причина в том, что называть его без квалификатора было бы слишком вводящим в заблуждение.

3 голосов
/ 11 октября 2010

Поскольку DoSomething принимает параметр.

DoSomething(a) будет допустимым.

Редактировать

Я немного неправильно прочитал вопросздесь.

Поскольку вы вызываете его как обычный статический метод, а не метод расширения, вам необходимо использовать префикс с именем класса.

Так что A_Ext.DoSomething(a); будет работать.

Если вы называете его как обычный статический метод, применяются все те же правила.

Ваш второй вариант работает, потому что B наследует A, и, следовательно, вы все равно в конечном итоге вызываете его как метод расширения, а третий не делает.

извините за первую версию выше, которая не работает.Я оставлю это, чтобы оставить комментарий актуальным.

2 голосов
/ 11 октября 2010

Методы расширения по-прежнему являются статическими, а не истинными вызовами экземпляров. Чтобы это работало, вам нужен конкретный контекст с использованием синтаксиса метода экземпляра (из Методы расширения (Руководство по программированию в C #) )

В вашем коде вы вызываете расширение метод с синтаксисом метода экземпляра. Тем не менее, промежуточный язык (IL), сгенерированный компилятором переводит ваш код в вызов статический метод. Следовательно принцип инкапсуляции не действительно нарушается. По факту, методы расширения не могут получить доступ частные переменные в типе они расширение.

Таким образом, хотя обычно оба синтаксиса работают, второй не имеет явного контекста, и может показаться, что сгенерированный IL не может получить контекст неявным образом.

2 голосов
/ 11 октября 2010

DoSomething требует, чтобы экземпляр A делал что-либо, и без квалификатора компилятор не может видеть, какой DoSomething вам нужно вызвать.Он не знает, как проверить A_Ext для вашего метода, если вы не квалифицируете его как this.

...