Использовать общие ограничения с интерфейсом

#c# #generics #interface #constraints

#c# #общие #интерфейс #ограничения

Вопрос:

У меня есть следующий код, в котором задействованы общие :

     public class MyWorkerClass<T> : IWorkerContract<T> //in IWorkerContract also i have same generic constraint that i have in this class.
      where T: INeedAction, new()
    {
        public void DoWork ( T item )
        {
             //Loop on each property of item...
             if ( ..if current property value implement from INeedAction, then condition for recursion.. )
             {
                  this.DoWork ( currentPropertyValue as INeedAction);
                  //Get error -> "Can not convert INeedAction to T"
             }
 

В принципе, у меня есть woker, который работает с объектом «A» (который должен реализовать интерфейс INeedAction).
Если какое-либо свойство этого объекта ‘A’ реализует тот же интерфейс самого объекта (интерфейс i INeedAction), тогда мне нужно выполнить рекурсию с той же логикой DoWork и для этого свойства.

Как ни странно, я получаю эту ошибку, которую я не понимаю: «Невозможно преобразовать INeedAction в T» Почему это, если я принудительно установил, что T должен реализовать INeedAction?

Ответ №1:

Давайте предположим, что Foo и Bar оба реализуют INeedAction , и Foo имеет свойство типа Bar .

Тогда a MyWorkerClass<Foo> представляет работу, которая может DoWork быть выполнена на a Foo . Пока все хорошо. Однако посмотрите, что происходит, когда DoWork вызывается и находит Bar свойство. Начиная с Bar реализации INeedAction , вы вызываете

 this.DoWork (bar as INeedAction);
 

Помните, что this это все еще MyWorkerClass<Foo> — вещь, над которой можно только работать Foo , но вы даете ей Bar возможность работать! Это не имеет смысла, не так ли? Вот почему вы не можете передать INeedWork принимающий параметр T .

Также обратите внимание, что DoWork это не является универсальным. Он принимает очень специфический тип — T . Это должно быть то же T самое, что используется в параметре типа класса.


Судя по вашему коду, я не думаю DoWork , что оно вообще должно быть универсальным. Он должен принимать INeedWork .

Комментарии:

1. Да, вы правы, изменение подписи так, чтобы она принимала только INeedWork, проще и работает по назначению. Еще раз спасибо за разъяснения