7

Вопрос по generics, inheritance, c# – undefined

У меня есть не элегантное решение для того, что мне нужно, но я ищу элегантное решение для его замены.

Следующий код не компилируется, но представляет то, что я хотел бы сделать:

interface IWebService
{
}

abstract class BaseClient<T>
{
}

class SpecializedClient : BaseClient<IWebService>
{
}

class ClientHelper<T> where T : BaseClient<*>
{
}

ГдеT вClientHelper<T> любой класс, который расширяетсяBaseClient независимо от типа шаблона, переданного в.

Нелегальное решение, которое я нашел:

class ClientHelper<T, U> where T : BaseClient<U> {}

Причина, по которой это становится не элегантным, заключается в том, что мой проект заканчивается классом, похожим на:

class MyClass<A, B, C, D, E, F, G> where A  : MyBaseClass<B, C, D, E, F, G>

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

  • Error: User Rate Limit ExceededoperationsError: User Rate Limit ExceededTError: User Rate Limit Exceeded

    от
  • Error: User Rate Limit ExceededTError: User Rate Limit Exceeded

    от Foran
  • Error: User Rate Limit ExceededClass<T>Error: User Rate Limit ExceededTError: User Rate Limit Exceeded

    от Foran
  • 0

    Один из вариантов выглядит так:

    interface IWebService
    {
    }
    
    interface IClient<out T>
    {
    }
    
    abstract class BaseClient<T> : IClient<T>
    {
    }
    
    class SpecializedClient : BaseClient<IWebService>
    {
    }
    
    class ClientHelper<T> where T : IClient<object>
    {
    }
    

    Однако это будет работать только если выBaseClient только возвращаетсяT и никогда не принимает это.

  • 5

    Ваш &

    quot; не элегантный & quot; Решение является правильным, если открытый интерфейс BaseClient каким-либо образом предоставляет ему параметр общего типа.

    Так предполагаяBaseClient являетсяnot как вы определили это:

    abstract class BaseClient<T>
    {
       //Something about T here
    }
    

    Тогда T является частью договора об открытом интерфейсеBaseClientи, следовательно, является частью договора об открытом интерфейсеClientHelper (опять же, предполагая, чтоBaseClient<U> выставляется через интерфейс ClientHelper).

    С другой стороны, давайте предположим, что на самом деле это так, как в вашем примере:

    abstract class BaseClient<T>
    {
       //Nothing about T here
    }
    

    В этом случае вы можете сделать:

    interface IBaseClient
    {
       //Nothing about T here
    }
    
    abstract class BaseClient<T> : IBaseClient
    { 
        // Whatever you like here
    }
    

    а такжеClientHelper будет выглядеть так:

    class ClientHelper<T> where T : IBaseClient
    {
    }