Il tipo non può essere utilizzato come parametro tipo “T” nel tipo o metodo generico – Perché?

Sto cercando di ereditare due modelli diversi da un’interfaccia. Questi Modelli dovrebbero essere passati come Lista o Raccolta ad un Metodo. Ora sto ricevendo questo messaggio di errore:

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

Qualcuno può spiegarmi per favore, cosa sto facendo male? : D

Codice demo:

 interface IModel where T : IModelItem { string Name { get; set; } IEnumerable Items { get; set; } } interface IModelItem { string Name { get; set; } } class FooModel : IModel { public FooModel() { Items = new List(); } public string Name { get; set; } public IEnumerable Items { get; set; } } class FooModelItem : IModelItem { public string Name { get; set; } } class Program { static void Main(string[] args) { var fooLists = new List(); var barLists = new ObservableCollection(); var service = new Service(); service.DoSomethingWith(fooLists); service.DoSomethingWith(barLists); } } class Service { public void DoSomethingWith(IEnumerable list) where T : IModel { foreach (var model in list) { Debug.WriteLine(model.Name); foreach (var item in model.Items) { Debug.WriteLine(item.Name); } } } } 

Il Progetto Demo può essere trovato su GitHub: https://github.com/SunboX/InheritanceTest/blob/master/InheritanceTest/Program.cs

Come esempio del perché non puoi farlo, immagina che, oltre a FooModel e FooModelItem , avessi BarModelItem . Ora diciamo che lo fai:

 IModel fooModel = new FooModel(); IModel iModel = fooModel; iModel.Items = new List(new BarModelItem()); FooModelItem fooModelItem = fooModel.Items.First(); 

Se fosse un codice valido, avresti avuto dei problemi, perché l’object che avresti riportato nell’ultima riga non sarebbe in realtà un FooModelItem ma un object BarModelItem !

Se leggi attentamente ogni riga, vedrai che l’unica linea errata ansible è la seconda. Ciò dimostra perché un IModel non può essere assegnato a un IModel , anche se FooModelItem : IModelItem . Non essere in grado di fare questo incarico è esattamente il motivo per cui la tua chiamata al metodo fallisce.

Puoi esaminare la covarianza e la contravarianza generiche per vedere come ciò può essere evitato in alcuni casi, sebbene non sia di aiuto nella tua situazione particolare senza modificare il tuo modello.