2013-09-27 6 views
2

Если у меня есть этот код:реализация необщего класс универсального интерфейса не наследуется

public interface IThing<T> where T : class 
{ 
    // ... 
} 

public class BaseThing<T> : IThing<T> where T : class 
{ 
    // ... 
} 

public class ThingA : BaseThing<string> 
{ 
    // ... 
} 

public class ThingB : BaseThing<Uri> 
{ 
    // ... 
} 

Этот код не удается:

List<IThing<object>> thingList = new List<IThing<object>>(); 

thingList.Add(new ThingA()); 
thingList.Add(new ThingB()); 

Даже если ThingA (косвенно) наследует (и должно быть пример) IThing<T>. Зачем? Is ThingA/ThingB не экземпляр IThing<T>?

+2

Читайте о ковариации и контравариантности. (Я не знаю достаточно, чтобы ответить на вопрос, кроме как знать, что эти понятия связаны.) – zimdanen

+2

Обратите внимание, что все «экземпляры» из 'IThing ' like 'IThing ', 'IThing ', 'IThing ' являются братьями и сестрами - между ними нет отношения наследования. Также нет отношения наследования с 'IThing ', что на самом деле совершенно другое (и также отличается от 'IThing <>' - [open generic] (http://stackoverflow.com/questions/2173107/what-exactly-is -an-открытого общего типа в сети)). –

ответ

7

Для этого потребуется, чтобы ваш интерфейс был ковариантным. Для получения дополнительной информации см. Covariance and Contravariance in Generics.

В этом случае, вы можете сделать эту работу с помощью:

// Add out here 
public interface IThing<out T> where T : class 
{ 
} 

Обратите внимание, что это место ограничения на интерфейсе и что вы можете делать с ним, однако, как это требует, чтобы тип T в интерфейс используется только как тип возвращаемого метода в интерфейсе и не используется как тип формальных параметров метода.

Если это нецелесообразно, другой вариант заключается в создании не общего интерфейса IThing, а также IThing<T>. IThing. Затем вы можете использовать List<IThing> для своей коллекции.

+0

Да, у меня есть свойства, определенные в интерфейсе, которые используют 'T' (например,« Список '), так что это не сработает. Есть ли что-нибудь еще, что я могу изменить в дизайне, который сделает эту работу, или я должен посмотреть на повторное архивирование этого? – qJake

+3

@SpikeX Вам нужно немного перестроить его. Один из вариантов заключается в создании не общего интерфейса «IThing» и его «IThing » реализовать. Затем вы могли бы создать «Список » и использовать его ... –

+0

Создание универсального интерфейса в дополнение к универсальному сделало трюк. Код компилируется, и даже лучше, MEF снова работает. Благодаря! – qJake

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