#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, проще и работает по назначению. Еще раз спасибо за разъяснения