2014-07-02 59 views
4

我想從一個接口繼承兩個不同的模型。應將這些模型作爲列表或集合傳遞給方法。現在我得到這個錯誤信息:類型不能用作泛型類型或方法中的類型參數'T' - 爲什麼?

The type 'InheritanceTest.FooModel' cannot be used as type parameter 'T' in the generic type or method 'InheritanceTest.Service.DoSomethingWith<T>(System.Collections.Generic.IEnumerable<T>)'. There is no implicit reference conversion from 'InheritanceTest.FooModel' to 'InheritanceTest.IModel<InheritanceTest.IModelItem>'. C:\Work\InheritanceTest\InheritanceTest\Program.cs 14 13 InheritanceTest 

有人可以請解釋我,我做錯了什麼? :d

演示代碼:

interface IModel<T> where T : IModelItem 
{ 
    string Name { get; set; } 

    IEnumerable<T> Items { get; set; } 
} 

interface IModelItem 
{ 
    string Name { get; set; } 
} 

class FooModel : IModel<FooModelItem> 
{ 
    public FooModel() 
    { 
     Items = new List<FooModelItem>(); 
    } 

    public string Name { get; set; } 
    public IEnumerable<FooModelItem> Items { get; set; } 
} 

class FooModelItem : IModelItem 
{ 
    public string Name { get; set; } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var fooLists = new List<FooModel>(); 
     var barLists = new ObservableCollection<BarModel>(); 

     var service = new Service(); 

     service.DoSomethingWith(fooLists); 
     service.DoSomethingWith(barLists); 
    } 
} 

class Service 
{ 
    public void DoSomethingWith<T>(IEnumerable<T> list) where T : IModel<IModelItem> 
    { 
     foreach (var model in list) 
     { 
      Debug.WriteLine(model.Name); 

      foreach (var item in model.Items) 
      { 
       Debug.WriteLine(item.Name); 
      } 
     } 
    } 
} 

示範項目可以在GitHub上找到: https://github.com/SunboX/InheritanceTest/blob/master/InheritanceTest/Program.cs

+0

'FooModelItem'和'IModelItem'之間的關係是什麼?我相信你可能用'class FooModel實現:IModel ' –

+0

更新了代碼以包含'IModelItem'和'FooModelItem' –

+0

Nikhil Agrawal可能是錯誤的,因爲這個問題與你以前的問題完全相同。這裏有一個協變/逆變難題。最好查看關於它們的其他問題,例如[this one](http://stackoverflow.com/q/1228173/395718)。 – Dialecticus

回答

4

至於爲什麼你不能做到這一點的例子,假設除了FooModelFooModelItem,你有BarModelItem。現在,讓我們說,你這樣做:

IModel<FooModelItem> fooModel = new FooModel(); 
IModel<IModelItem> iModel = fooModel; 
iModel.Items = new List<BarModelItem>(new BarModelItem()); 

FooModelItem fooModelItem = fooModel.Items.First(); 

如果這是有效的代碼,你會遇到麻煩,因爲該項目你會回來的最後一行不會實際上是一個FooModelItemBarModelItem

如果仔細閱讀每一行,您會看到唯一可能的錯誤行是第二行。這證明爲什麼IModel<FooModelItem>不能被分配給IModel<IModelItem>,即使FooModelItem : IModelItem。無法完成該任務正是您的方法調用失敗的原因。

您可以查看泛類協變性和逆變性,以瞭解在某些情況下如何避免這種情況,儘管在沒有修改模型的情況下它無助於您的特定情況。

+0

謝謝,我確實在@Eric Lippert發現了類似的答案:http://stackoverflow.com/a/17440148/1692735 –

相關問題