Как стать автором
Обновить

В дженериках C# мог бы быть полезен “this type”

Время на прочтение2 мин
Количество просмотров3.7K
Разбирая наш код, нашел место, которое явно требовало бы некоторой подчистки. Но чтобы почистить, в языке нужна бы еще фича, которую и хочу обсудить. Я поднимал этот вопрос также и на StackOverflow. Был поддержан авторитетным камрадом.

Возьмем два класса, один наследуют от другого. Базовый класс – дженерик, в котором есть метод, который в производном закрытом типе должен возвращать экземпляр этого самаого закрытого типа.

Например, так (обратите внимание на ??? в тексте):

public class Adapter<T>
{
  public virtual ??? DoSomething()
  {
     ...
  }
}

public class AdaptedString : Adapter<String>
{
  public override AdaptedString DoSomething()
  {
    ...
  }
}


* This source code was highlighted with Source Code Highlighter.


Так сделать нельзя, так как в нет способа сослаться на тип, получающийся при “закрытии” дженерика. Нет такого ключевого слова, которым можно заменить “???”, чтобы указать, что этот метод будет возвращать экземпляр производного закрытого класса.

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

public class Adapter<TThis,T>
{
  public virtual TThis DoSomething()
  {
    ...
  }
}

public class AdaptedString : Adapter<AdaptedString,String>
{
  public override AdaptedString DoSomething()
  {
    ...
  }
}


* This source code was highlighted with Source Code Highlighter.


А если в базовом классе нужно обращаться к методам экземпляра типа TThis, то приходится добавлять констрейнт. И получается совсем страшно:

public class Adapter<TThis,T>
  where TThis : Adapter<TThis, T>
{
  protected int _field;
  ...
  public bool Compare( TThis obj )
  {
    return _field == obj._field;
  }
}

public class AdaptedString : Adapter<AdaptedString,String>
{
  ...
}


* This source code was highlighted with Source Code Highlighter.


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

Кажется было бы гораздо удобнее, если бы можно было как-то указать, что “TThis” должен быть этим типом. Может быть использовать какое-нибудь ключевое слово. Типа “thistype”, хотя это тоже выглядит страшно. Может быть констрейнт ввести:
where TThis: this type

А то ведь получается, что этот окружной путь позволяет запросто накосячить:

class TypeA : Adapter<TypeA, string>

class TypeB : Adapter<TypeA, string> // Bug!


* This source code was highlighted with Source Code Highlighter.
Теги:
Хабы:
Всего голосов 10: ↑6 и ↓4+2
Комментарии19

Публикации

Работа

.NET разработчик
44 вакансии

Ближайшие события