2015-09-15 5 views
2

У меня есть эти 3 абстрактные классы:Generic тип ошибки параметр

public abstract class DataObject {} 
public abstract class BusinessObject<T> where T : DataObject {} 
public abstract class UIObject<T> where T : BusinessObject<DataObject> {} 

Я могу создать CustomerDataObject, который вытекает из DataObject, а CustomerBusinessObject, который вытекает из BusinessObject<CustomerDataObject>, но я не могу создать CustomerUIObject класс:

Тип CustomerBusinessObject не может быть использован в качестве параметра типа T в общем типе или методе UIObject<T>. Нет никакого неявного эталонного преобразования от CustomerBusinessObject до BusinessObject<DataObject>.

Что я делаю неправильно?

+0

Том Ортон описывает, почему это не но правильное решение этой проблемы зависит от того, как вы хотите использовать эти типы (и их параметры типа). Если вы разместите более подробную информацию о своем прецеденте, мы сможем предложить лучший подход. –

+0

@WillVousden Например, абстрактный класс BusinessObject предоставляет некоторые методы и события, которые совместно используются всеми конкретными бизнес-объектами. В этом случае мне нужен параметр generic type, потому что DataObject, связанный с BusinessObject, должен быть доступен, поэтому он предоставляет это свойство: public public T DataObject {get; защищенный набор; } ' –

+0

Но как' UIObject' взаимодействует с параметрами своего типа?Похоже, что ему может понадобиться только знать тип DataObject, из которого он мог бы построить сам тип BusinessObject. –

ответ

2

Для Why - вы уже знаете

Теперь есть способ, что вы можете сделать это - без изменения логики:

Вы можете добавить двойное ограничение:

public abstract class DataObject {} 
public abstract class BusinessObject<T> where T : DataObject {} 
public abstract class UIObject<T,U> where T : BusinessObject<U> where U:DataObject {} 

Таким образом, вы явно указываете компилятору, что U может быть типом, который является результатом DataObject - это именно то, что ваш CustomerDataObject.

Но вам нужно будет добавить:

class CustomerDataObject:DataObject 
{} 
class CustomerBusinessObject :BusinessObject<CustomerDataObject> 
{} 
class CustomerUIObject :UIObject<CustomerBusinessObject,CustomerDataObject> 
{} 

Таким образом Вы указываете CustomerDataObject, который наследует от DataObject это именно то, что вы имели в виду в первую очередь

+0

Спасибо, это работает, хотя это немного белое. Не считаете ли вы этот подход плохой практикой? –

+0

Это действительно зависит от реальной ситуации. В общем, это то, что общие ограничения хороши. Весь мой код здесь говорит компилятору: Эй - Пожалуйста, разрешите 'BusinessObject ' распознаваться в 'где T: BusinessObject {}' –

2

Вы явно о том, что T для UIObject наследует BusinessObject<DataObject> но ваш тип CustomerBusinessObject фактически наследует BusinessObject<CustomerDataObject>, который является другим типом.

У вас есть CustomerBusinessObject inherit BusinessObject<DataObject>, но тогда в реализации всегда используйте CustomerDataObject? Это исправит эту ошибку, но может быть не совсем то, что вы хотите.

public class CustomerBusinessObject : BusinessObject<DataObject> { } 
1

Чтобы решить эту проблему, вам необходимо использовать общие признаки.

public abstract class UIObject<T,U> where T : BusinessObject<U> 
+0

Компилятор жалуется на преобразование бокса, я добавил '' где U: DataObject'', и он сработал. –

+0

Да .... Я на самом деле добавил, что когда первоначально ответили, но мыслительный родительский класс в любом случае выполнил проверку ограничения для DataObject, так отредактировал его ..... Спасибо, что сообщили мне об ошибке. – Viru

Смежные вопросы