2010-11-09 4 views
4
interface IModel {} 

class MyModel : IModel {} 

interface IRepo<T> 
    where T: IModel { } 

class Repo : IRepo<MyModel> { } 

//EDIT: A smaller example 
IRepo<IModel> repo = new Repo(); // Cannot implicitly convert.. An explicit convertion exists. Missing cast? 

// Old example: 
/* 
The type 'Repo' cannot be used as type parameter 'C' in the generic type or method. 
'Castle.MicroKernel.Registration.ComponentRegistration<S>.ImplementedBy<C>()'. 
==> There is no implicit reference conversion from 'Repo' to 'IRepo<IModel>'. 
*/ 
container.Register(
    Component.For<IRepo<IModel>>() 
    .ImplementedBy<Repo>()); 

Но Repo происходит от IRepo, а MyModel получен из IModel. Почему это не работает?Производный тип не может быть неявно преобразован в базовый интерфейс

Я попытался добавить неявный оператор на Repo, но это не разрешено конвертировать между интерфейсами ..

ли это решается путем совместного/контру varience вещи из C# 4 (Нет, я не имею подскажите, о чем я говорю :))?

ответ

2

Ваша интуиция была права. Это ковариационная проблема. Видите ли, IRepo<IModel> и IRepo<MyModel> не совпадают.

Для обеспечения ковариантных типов, вы можете это исправить с модификатором out в C# 4:

interface IRepo<out T> where T: IModel {} 

Если вы не на C# 4 все же, вам нужно будет затянуть использование:

IRepo<MyModel> repo = new Repo(); 
+0

Спасибо. Угадайте, что пришло время подумать об обновлении до C# 4, затем .. – simendsjo

3

Вы правы. Это не работает из-за Co/Contravariance. Предполагается, что он будет работать на C# 4 (я не проверял его, потому что мне никогда не нужно было такого: P).

Хорошее объяснение о том, как это работает, можно найти здесь: http://blogs.msdn.com/b/csharpfaq/archive/2010/02/16/covariance-and-contravariance-faq.aspx

+0

Это не работает из коробки на C# 4. Интерфейс IREPO должен быть изменен с помощью модификатора ковариации: 'out'. –