2008-09-11 4 views
7

J'ai une collection qui implémente une interface qui étend à la fois IList < T> et List.Comment résoudre l'ambiguïté d'appel entre Generic.IList <T> .this [] et IList.this []?

public Interface IMySpecialCollection : IList<MyObject>, IList { ... } 

Cela signifie que j'ai deux versions de l'indexeur.

Je souhaite la mise en œuvre générique à utiliser, donc je mets en œuvre que l'on normalement:

public MyObject this[int index] { .... } 

Je ne ai besoin de la version IList pour la sérialisation, donc je mets en œuvre explicitement, de le garder caché:

object IList.this[int index] { ... } 

Cependant, dans mes tests unitaires, les éléments suivants

MyObject foo = target[0]; 

résultats dans un com erreur piler

L'appel est ambigu entre les méthodes ou propriétés

Je suis un peu surpris de cela; Je crois que je l'ai déjà fait et ça marche bien. Qu'est-ce que j'oublie ici? Comment puis-je faire coexister IList < T> et IList dans la même interface?

Modifier IList < T> ne pas mettre en œuvre IList, et je doit mettre en œuvre IList pour la sérialisation. Je ne suis pas intéressé par les solutions de contournement, je veux savoir ce qui me manque.

Modifier à nouveau: J'ai dû supprimer IList de l'interface et la déplacer dans ma classe. Je ne veux pas faire cela, car les classes qui implémenteront l'interface finiront par être sérialisées en Xaml, ce qui nécessite des collections pour implémenter IDictionary ou IList ...

+0

Puis-je demander comment vous sérialisation d'un indexeur personnalisé? Lorsque j'ai essayé d'indexer un indexeur personnalisé (pour WCF), j'obtiens un message ASP-écran-de-mort indiquant que les indexeurs personnalisés ne peuvent pas être sérialisés. J'ai finalement abandonné l'idée. –

Répondre

3

Vous ne pouvez pas le faire avec

public interface IMySpecialCollection : IList<MyObject>, IList { ... }

Mais vous pouvez faire ce que vous voulez avec une classe, vous aurez besoin de faire les mises en œuvre pour l'une des interfaces explicites. Dans mon exemple, j'ai rendu IList explicite.

public class MySpecialCollection : IList<MyObject>, IList { ... }

IList<object> myspecialcollection = new MySpecialCollection(); IList list = (IList)myspecialcollection;

Avez-vous envisagé d'avoir IMySpecialCollection mettre en œuvre ISerializable pour la sérialisation? La prise en charge de plusieurs types de collection me semble un peu erronée. Vous voudrez peut-être aussi regarder la conversion de IList en IEnumerable pour la sérialisation, car IList ne fait qu'encapsuler IEnumerable et ICollection.

+1

+1 pour remarquer que cette erreur se produit lors de l'utilisation d'une interface mais pas d'une classe. 0 pour ISerializable + Xaml: P – Lucas

-1

La liste < T> implique IList, donc c'est un mauvais idée d'utiliser les deux dans la même classe.

+1

IList n'implémente pas IList. Et j'ai besoin d'implémenter IList à des fins de sérialisation. – Will

1

Malheureusement, vous ne pouvez pas déclarer deux indexeurs avec la même liste de paramètres. Le paragraphe suivant est tiré d'ici C# Programming Guide - Using Indexers "Remarks" section:

La signature d'un indexeur se compose du nombre et des types de ses paramètres formels. Il n'inclut pas le type de l'indexeur ni les noms des paramètres formels. Si vous déclarez plusieurs indexeurs dans la même classe, ils doivent avoir des signatures différentes.

Vous devrez déclarer un ensemble de paramètres différent si vous souhaitez utiliser le second indexeur.

+1

Vous ne pouvez pas avoir 2 indexeurs 'ceci', mais vous pouvez avoir une 'chaîne IDataErrorInfo.this' et une 'T IList .this'. Vous devrez lancer l'objet avant d'accéder à l'indexeur, mais cela fonctionne. –

-1

Changer votre implémentation générique ...

T IList<T>.this[int index] { get; set; } 

Cela dit explicitement que 'ceci' est qui.

+0

avec les deux mis en œuvre explicitement, vous devez lancer la liste pour utiliser l'un ou l'autre, ce qui n'est pas ce qu'il veut. il veut par défaut le générique et cacher le non générique. – Lucas

2

C'est dupe de my question here

En résumé, si vous faites cela, il résout le problème:

public Interface IMySpecialCollection : IList<MyObject>, IList 
{ 
    new MyObject this[int index]; 
    ... 
} 
Questions connexes