2009-08-04 12 views
2

Je dispose d'un deux interfaces définies comme suit:C# Génériques et collections

public interface IFoo 
{ 
... 
} 

Public interface IFooWrapper<T> where T : IFoo 
{ 
    T Foo {get;} 
} 

Je veux être en mesure de déclarer une collection de IFooWrappers, mais je ne veux pas de préciser la mise en œuvre de IFoo.

Idéalement je veux faire quelque chose comme:

IList<IFooWrapper<*>> myList; 

Je ne peux pas trouver un moyen de contourner cela.

+0

Voir aussi: http://stackoverflow.com/questions/833447/833475#833475 –

Répondre

2
public interface IFoo 
{ 
... 
} 

public interface IFooWrapper : IFoo 
{ 
... 
} 
public interface IFooWrapper<T> : IFooWrapper 
where T : IFoo 
{ 
... 
} 
IList<IFooWrapper> myList; 

c'est une façon de faire ce que vous voulez

+0

Mon premier pensée. –

2

Quel est le problème avec

IList<IFooWrapper<IFoo>> myList? 
+0

En effet! Liste > myList = nouvelle liste >(); – redcalx

+1

Sauf que cela ne fonctionnera pas ... par exemple, IFooWrapper n'hérite pas IFooWrapper , même si Foo implémente IFoo ... (sauf si vous utilisez C# 4 qui implémente la covariance) –

+1

Liste > fooWrapperList = nouvelle liste >(); Concretewrapper = new ConcreteFooWrapper (); fooWrapperList.Add (concreteWrapper); – redcalx

0
public class FooWrapper : IFooWrapper<IFoo> 
0

Ce que je vais suggérer est trop pour la plupart des situations, car, généralement, vous pouvez créer une interface plus haut dans la hiérarchie que vous pouvez utiliser. Cependant, je pense que c'est la solution la plus souple d'une certaine façon, et la représentation la plus fidèle de ce que vous voulez:

public interface IFooWrapperUser<U> { 
    U Use<T>(IFooWrapper<T> wrapper); 
} 

public interface IFooWrapperUser { 
    void Use<T>(IFooWrapper<T> wrapper); 
} 

public interface IExistsFooWrapper { 
    U Apply<U>(IFooWrapperUser<U> user); 
    void Apply(IFooWrapperUser user); 
} 

public class IExistsFooWrapper<T> : IExistsFooWrapper { 
    private IFooWrapper<T> wrapper; 
    public IExistsFoo(IFooWrapper<T> wrapper) { 
     this.wrapper = wrapper; 
    } 

    public U Apply<U>(IFooWrapperUser<U> user) { 
     return user.Use(foo); 
    } 

    public void Apply(IFooWrapperUser user) { 
     user.Use(foo) 
    } 
} 

Maintenant, vous pouvez créer une instance d'un IList<IExistsFooWrapper> qui peut être utilisé comme si elle est un IList<IFooWrapper<*>>. L'inconvénient est que vous devrez créer une classe pour encapsuler la logique que vous voulez exécuter sur chaque élément:

private class FooPrinter : IFooWrapperUser<string> { 
    public string Apply<T>(IFooWrapper<T> wrapper) { 
     return wrapper.Foo.ToString(); 
    } 
} 

... 
    IFooWrapperUser<string> user = new FooPrinter(); 
    foreach (IExistFooWrapper wrapper in list) { 
     System.Console.WriteLine(wrapper.Apply(user)); 
    } 

...