2009-09-08 2 views
0

Я имею следующие интерфейсы:Pass унаследовал интерфейс к способу

public interface IBase 
{ 
    int id1 { get; set; } 
} 

public interface IDerived : IBase 
{ 
    int id2 { get; set; } 
} 

И следующую программу (пример):

class Program 
{ 
    static void Main(string[] args) 
    { 
     IList<IDerived> derived = null; 
     Check(derived); 
    } 

    static void Check(IList<IBase> base) 
    { 
    } 
} 

Я получаю эту ошибку compliation: не может преобразовать от 'System.Collections.Generic.IList<IDerived>' до 'System.Collections.Generic.IList<IBase>'

Если я пытаюсь передать только один экземпляр, а не список, он работает, и что мне здесь не хватает?

Спасибо,

+0

Не является ли 'base' зарезервированным ключевым словом в C#? – aolde

+0

Не прошло и недели, когда кто-то не задавал вопрос о ковариации. –

ответ

3

Вам нужно будет нанести элементы IList на IBase. Вот пример использования Linq расширения:

Check(derived.Cast<IBase>()); 
+0

Кажется, что это работает, только если я изменил параметр метода «Проверить» на IEnumerable <> вместо IList <> (что похоже на аналогичную проблему с обсуждаемой здесь ... IList <> реализует IEnumerable <>). – nirpi

+0

Извините, еще рано утром ... Добавление ToList() устраняло проблему: Check (found.Cast () .ToList()); Спасибо! – nirpi

3

Это происходит из-за отсутствия ковариации по типам интерфейсов в C# 3, C# 4 позволит вам указать ковариации и контрвариацию по типам интерфейсов.

К сожалению, это одна из тех вещей, которые просто не работают так, как вы думаете, это должно быть в C# 3.

2

Экземпляр IList<IDerived> не является экземпляром IList<IBase>. Во-первых, вы не можете называть .Add(new ConcreteBase()). (где ConcreteBase инвентарь IBase)

+0

вызов .Add (новый ConcreteBase()) - это не то же самое, что передавать «Derived Instance» с использованием ссылки «Base Type». – 2009-09-08 20:53:55

0

И все же это будет работать ...

static void Main(string[] args) 
    { 
     List<IDerived> derived = null; 
     Check(derived.ToArray()); 
    } 

    static void Check(IBase[] asdf) 
    { 
    } 

Одна из нескольких причин я предпочитаю необработанный массив [] или IEnumerable <> для интерфейсов как на аргументы и возвращаемые значения. Но если вы предпочитаете использовать List/IList, вы все равно можете сделать следующее:

static void Main(string[] args) 
    { 
     IList<IDerived> derived = null; 
     Check(derived); 
    } 

    static void Check<T>(IList<T> asdf) where T : IBase 
    { 
    } 
Смежные вопросы