2009-09-08 70 views
0

我有以下接口:通行證繼承接口的方法

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

是不是'基地'保留在C#中的關鍵字? – aolde 2009-09-08 20:37:12

+0

沒有一個星期過去了,因爲有人不問關於協方差的問題。 – 2009-09-08 22:21:01

回答

3

您需要將IList項目投射到IBase。下面是使用LINQ擴展的示例:

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

這似乎只有當我將「檢查」方法參數更改爲IEnumerable <>而不是IList <>(這似乎與此處討論的類似的問題... IList <>實現IEnumerable <>)時才起作用。 – nirpi 2009-09-09 04:36:18

+0

對不起,一大早... 添加ToList()修復了問題: 檢查(derived.Cast ().ToList()); 謝謝! – nirpi 2009-09-09 06:15:23

3

這是由於在C#3接口類型缺乏協方差,C#4將允許你指定的接口類型的協變和逆變。

不幸的是,只是不工作,你認爲它應該在C#3

2

IList<IDerived>實例是不是IList<IBase>實例的方法的事情之一。首先,你不能打電話給.Add(new ConcreteBase())。 (ConcreteBase implements IBase

+0

調用.Add(new ConcreteBase())與使用「基類型」引用傳遞「派生實例」不同。 – 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的<>返回值。但是,如果你更喜歡使用列表/ IList你仍然可以做到以下幾點:

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

    static void Check<T>(IList<T> asdf) where T : IBase 
    { 
    }