Проблема с методами расширения и общими ограничениями - PullRequest
3 голосов
/ 23 октября 2010

У меня есть базовый интерфейс и несколько унаследованных интерфейсов. Существуют методы расширения для базового интерфейса, которые модифицируют объект и возвращают новый экземпляр базового класса (IChildA.Touch() => IBase, IBase.Touch() => IBase).

Для одного пути наследования (IChildB и потомков) я хочу реализовать методы расширения, которые возвращают объект того же типа, что и вызывающий объект (IGrandChildB.Touch() => IGrandChild). Для этого я хотел бы указать один общий метод расширения, который ограничен IChildB потомками.

Пока это работает, но теперь компилятор не может разрешить вызов с IChildA. Он пытается использовать метод расширения для пути IChildB и завершается неудачей вместо использования метода расширения для интерфейса IBase. Есть ли элегантный способ исправить это?

public interface IBase {}

public interface IChildA : IBase {}

public interface IChildB : IBase {}

public static class BaseExtensions
{
  public static IBase Touch(this IBase self) { return self; }
  public static T Touch<T>(this T self) where T : IChildB { return self; }
}

public static class TestClass
{
  public static void Test()
  {
    IChildA a = null;
    IBase firstTry = a.Touch();  //Cannot resolve to BaseExtensions.DoSomething(this IBase obj)
    IBase secondTry = ((IBase)a).Touch();  //Resolves to BaseExtensions.DoSomething(this IBase obj)

    IChildB b = null;
    IChildB touchedB = b.Touch();
  }
}

1 Ответ

1 голос
/ 23 марта 2011

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

public interface IBase {}

public interface IChildA : IBase {}

public interface IChildB : IBase {}

public static class BaseExtensions
{
    public static T Touch<T>(this T self) where T : IBase { return self; }
}

public static class TestClass
{
    public static void Test()
    {
        IChildA a = null;
        IBase firstTry = a.Touch();

        IChildB b = null;
        IChildB touchedB = b.Touch();
    }
}
...