Почему это. квалификатор требуется при вызове метода interfaceextension внутри класса, который реализует интерфейс?

#c# #interface #extension-methods

#c# #интерфейс #методы расширения

Вопрос:

Данный интерфейс

 public interface IHaveError
{
    string ErrorMessage { get; set; }
}
  

Расширение

 public static class HaveErrorExtensions
{
    public static void SetErrorMessage(this IHaveError target, string message)
    {
        target.ErrorMessage = message;
    }
}
  

Класс

 public class HaveError : IHaveError
{
    public string ErrorMessage { get; set; }

    public void DoSomething()
    {
        this.SetErrorMessage(message);
    }
}
  

Почему this. требуется при вызове метода расширения? Имя не разрешается без него.

Ответ №1:

Вот как методы расширения работают в спецификации языка C #. Если вы прочитали раздел «7.6.5.2 Вызовы метода расширения», в нем в основном говорится, что у вас должен быть вызов метода одной из следующих форм:

 expr . identifier ( )
expr . identifier ( args )
expr . identifier < typeargs > ( )
expr . identifier < typeargs > ( args )
  

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

В этом случае он this. становится expr. указанным выше, так что вышеуказанное может быть преобразовано в вызов статического метода для типа, где это метод расширения, определенный как:

 C . indentifier ( expr , args )
  

В вашем случае, для того, чтобы компилятор «нашел» (или даже искал) вызов метода, вам необходимо указать некоторый тип «expr». Уточняет явный this. . Это заставляет компилятор принимать это:

 this.SetErrorMessage(message);
  

И найдите соответствующий метод расширения, который работает с типом, переводя его в:

 HaveErrorExtensions.SetErrorMessage(this, message);
  

Ответ №2:

Методы расширения — это просто статические методы с некоторым синтаксическим сахаром (очень вкусный синтаксический сахар!), применяемый компилятором. Ссылка на объект, по которой вызывается метод, на самом деле является первым аргументом метода.

Компилятор должен знать, какой экземпляр вы имеете в виду. Он не может угадать.

Ответ №3:

Потому что this ссылается на текущий объект, с которым вы работаете. Без this компилятор не знает, к чему применять метод расширения.