Вызывать методы расширения интерфейса от разработчика странно в C # - PullRequest
6 голосов
/ 15 сентября 2010

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

Кто-нибудь знает почему?

Есть ли более простой способ получить общую реализацию для интерфейса?

Это раздражает меня, так как я страдаю множественным наследованием / изъятием миксина.

Пример игрушки:

public interface ITest
{
    List<string> TestList { get; }
}

public static class TestExtensions
{
    private const string Old = "Old";
    private const string New = "New";

    public static void ManipulateTestList(this ITest test)
    {
        for (int i = 0; i < test.TestList.Count; i++)
        {
            test.TestList[i] = test.TestList[i].Replace(Old, New);
        }
    }
}

public class Tester : ITest
{
    private List<string> testList = new List<string>();
    public List<string> TestList
    {
        get { return testList; }
    }

    public Tester()
    {
        testList.Add("OldOne");
        testList.Add("OldTwo");

        // Doesn't work
        // ManipulateTestList();

        // Works
        this.ManipulateTestList();
    } 
}

Ответы [ 3 ]

4 голосов
/ 15 сентября 2010

Я задал этот точный вопрос языковой команде напрямую. У меня нет электронной почты, но в основном ответ (от Mads, IIRC) был:

  • чтобы уменьшить пространство / сложность поиска - т. Е. Не нужно учитывать все доступные методы расширения (и сокращать их), если сначала нет выражения.
  • чтобы уменьшить вероятность того, что метод расширения "захватит" обычный метод (т. Е. Будет лучшим совпадением) неожиданно

Лично мне бы хотелось, чтобы он работал последовательно - первое не кажется большой проблемой (но потом я не пишу компиляторы), и ни не подходит к тому факту, что обычно this.* - это необязательная вещь (которая может влиять, например, на местные правила стиля кода, т. Е. «Ты должен использовать this.»).

3 голосов
/ 15 сентября 2010

Соответствующий раздел в спецификации языка гласит:

7.6.5.2 Вызовы метода расширения

В вызове метода (§7.5.5.1) одна из форм

  • expr . идентификатор ( )
  • expr . идентификатор ( args )
  • expr . идентификатор < typeargs > ( )
  • expr . идентификатор < typeargs > ( args )

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

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

1 голос
/ 15 сентября 2010

Методы расширения - это трюк компилятора, который работает с объектом, который перенаправляет вызов статическому методу в другой статический класс.'этот.это объект, который компилятор передает статический метод.Нерабочим примером является просто компилятор, сообщающий, что метод не является и метод экземпляра ограничен классом.

...