2010-06-14 7 views
0

Quelqu'un peut-il me dire pourquoi cela ne fonctionne pas? J'aurais pensé que la contrainte le rendrait valide.C# Problème de génériques

public class ClassA<T> where T : ICommon 
{ 
    public ClassA() 
    { 
     ClassB b = new ClassB(); 
     IEnumerable<T> alist = new List<T>; 
     b.Items = alist; 
     //Error: cannot convert from IEnumerable<T> to IEnumerable<ICommon>' 
    } 

} 


public class ClassB 
{ 
    public IEnumerable<ICommon> Items { get; set;} 
    .... 
} 

Répondre

12

Cela fonctionne en C# 4 avec un coup sec, mais pas en C# 3. Qu'est-ce que vous cherchez est variance générique, qui a été pris en charge dans le CLR depuis .NET 2.0, mais pas dans C# jusqu'à v4.

Même en C# 4, vous devez également contraindre T à être un type de référence - car la covariance ne fonctionne pas sur les types de valeur. Par exemple, List<int> ne peut pas être converti en IEnumerable<IComparable> même si int implémente IComparable.

Après avoir pincé votre code un peu (il y avait quelques fautes de frappe, efficace), ce compile avec le compilateur C# 4:

using System.Collections.Generic; 

public interface ICommon {} 

// Note the "class" part of the constraint 
public class ClassA<T> where T : class, ICommon 
{ 
    public ClassA() 
    { 
     ClassB b = new ClassB(); 
     IEnumerable<T> alist = new List<T>(); 
     b.Items = alist; 
    } 
} 

public class ClassB 
{ 
    public IEnumerable<ICommon> Items { get; set;} 
} 

Si vous êtes coincé dans C# 3 et .NET 3.5, une alternative serait d'utiliser Cast<T>():

b.Items = alist.Cast<ICommon>(); 
+0

Intéressant, merci! (Et mon code scrappy maintenant rangé, monsieur;) - embarrassingly bâclée sans intellisense!) – UpTheCreek

3

on appelle covariance (? ou contre, je ne suis pas sûr), et travaille uniquement en C# 4.0.
Vous ne pouvez pas diffuser IEnumerable<Common> à IEnumerable<ICommon>. (Quand commune met en œuvre ICommon.)

Essayez d'utiliser

b.items = from f in alist select (T)f;