2009-10-07 7 views
2

J'essaye de monter un paramètre passé en tant qu'objet (qui est un upcast d'un objet de type IEnumerable) vers IEnumerable où Foo implémente IFoo.Comment faire pour passer un objet de type IEnumerable <Foo> vers IEnumerable <IFoo> s'il est passé à la fonction en tant qu'objet?

Voici un exemple de ce que j'aimerais faire, mais cela ne fonctionne pas.

public void F(object o) 
{ 
    //I know the object o is of type IEnumerable<Foo> where Foo implements IFoo 
    IEnumerable<IFoo> ifoos = (IEnumerable<IFoo>) o); 
} 

Existe-t-il une solution? Je ne veux pas faire la fonction F Foo spécifique, mais je ne peux pas à jeter à l'interface A moins que je fais:

IEnumerable<IFoo> ifoos = (IEnumerable<Foo>) o).Select(f => (IFoo) f); 

Merci

Giuseppe

Répondre

10

Avant .NET 4.0, vous pouvez 't - IEnumerable<T> est invariant avant .NET 4.0.

Avec .NET 4.0, le code que vous avez posté fonctionnera correctement.

Dans .NET 3.5, vous pouvez utiliser Enumerable.Cast:

public void F(object o) 
{ 
    IEnumerable<IFoo> ifoos = ((IEnumerable) o).Cast<IFoo>(); 
} 

En gros, cela utilise le faiblement typé IEnumerable (tous deux IEnumerable<Foo> et IEnumerable<IFoo> étendent, de sorte que le casting sera bien) et applique alors la méthode Cast<T>, qui va essentiellement enchaîner un autre itérateur pour effectuer une distribution sur chaque élément. Cette distribution fonctionnera certainement si Foo : IFoo, ainsi vous ira bien.

Dans .NET 2.0, vous devriez écrire vous-même essentiellement Cast, ce qui est assez facile - surtout si vous n'avez pas besoin de faire des raccourcis:

public static IEnumerable<TResult> Cast<TSource, TResult> 
    (IEnumerable<TSource> source) 
{ 
    foreach(TSource item in source) 
    { 
     yield return (TResult) (object) item; 
    } 
} 

Le double Cast est un peu maladroit, mais cela fonctionne ...

+0

Plus d'informations sur la covariance/contravariance dans .NET 4: http://msdn.microsoft.com/en-us/library/dd233054%28VS.100%29.aspx et les rubriques connexes dans le tableau en bas. –

+0

Ou par l'accès précoce 2ème édition de C# en profondeur et lire le chapitre 13 :) (http://manning.com/skeet2) –

+0

Réponse incroyablement rapide, repérer sur MERCI! –

1

Une méthode générique serait-elle acceptable?

interface IFoo { } 
class Foo : IFoo { } 
static void F<T>(IEnumerable<T> data) where T : IFoo 
{ 
    foreach(T item in data) { 
     // compiler knows that `item` is an `IFoo` etc 
    } 
} 

... 
List<Foo> foos = new List<Foo>(); 
F(foos); 

Sinon; Attendez jusqu'à .NET 4.0/C# 4.0/VS2010.

+0

Ce serait si je créais la fonction pour scratch, mais je suis en train de peaufiner le corps d'une fonction existante afin qu'elle puisse gérer d'autres types qui mettent en œuvre IFoo. –

Questions connexes