2008-09-11 17 views
7

Ho una collezione che implementa un'interfaccia che estende sia IList < T> sia List.Come risolvere l'ambiguità di chiamata tra Generic.IList <T> .questo [] e IList.questo []?

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

Ciò significa che ho due versioni dell'indicizzatore.

vorrei che l'implementazione generica da utilizzare, così ho attuare che uno normalmente:

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

ho solo bisogno la versione IList per la serializzazione, così ho attuare in modo esplicito, di tenerlo nascosto:

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

Tuttavia, nel mio test di unità, il seguente

MyObject foo = target[0]; 

risultati in un com piler errore

La chiamata è ambigua tra le seguenti metodi o proprietà

Sono un po 'sorpreso di questo; Credo di averlo fatto prima e funziona bene. Cosa mi manca qui? Come posso ottenere IList < T> e IList per coesistere all'interno della stessa interfaccia?

Modifica IList < T> fa non implementare IList, e io deve implementare IList per la serializzazione. Non sono interessato a soluzioni alternative, voglio sapere cosa mi manca.

Modifica di nuovo: Ho dovuto rilasciare IList dall'interfaccia e spostarlo sulla mia classe. Non voglio farlo, poiché le classi che implementano l'interfaccia alla fine verranno serializzate su Xaml, che richiede collezioni per implementare IDictionary o IList ...

+0

Posso chiederle come si sta serializzare un indicizzatore personalizzato? Quando ho provato ad indicizzare un indicizzatore personalizzato (per WCF), ricevo un messaggio giallo-schermo-di-morte in ASP che dice che gli indicizzatori personalizzati non possono essere serializzati. Alla fine ho rinunciato all'idea. –

risposta

3

Non si può fare questo con

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

Ma si può fare quello che vuoi con una classe, è necessario rendere le implementazioni per una delle interfacce esplicite. Nel mio esempio ho reso esplicito IList.

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

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

Avete considerato avendo IMySpecialCollection implementare ISerializable per la serializzazione? Il supporto di più tipi di raccolta mi sembra un po 'sbagliato. Si potrebbe anche voler guardare a lanciare IList a IEnumerable per la serializzazione poiché IList include solo IEnumerable e ICollection.

+1

+1 per aver notato che questo errore si verifica quando si utilizza un'interfaccia ma non una classe. 0 per ISerializable + Xaml: P – Lucas

-1

Elenco < T> implica IList, quindi è un brutto idea di usare entrambi nella stessa classe.

+1

IList non implementa IList. E ho bisogno di implementare IList per scopi di serializzazione. – Will

1

Purtroppo non è possibile dichiarare due indicizzatori con lo stesso elenco di parametri. Il seguente paragrafo è preso da qui C# Programming Guide - Using Indexers "Remarks" section:

La firma di un indicizzatore è costituita dal numero e dai tipi dei relativi parametri formali. Non include il tipo di indicizzatore o i nomi dei parametri formali. Se dichiari più di un indicizzatore nella stessa classe, devono avere firme diverse.

Si dovrà dichiarare un diverso insieme di parametri se si desidera utilizzare il secondo indicizzatore.

+1

Non puoi avere 2 indicizzatori 'questo', ma puoi avere un 'stringa IDataErrorInfo.this' e un 'T IList .questo'. Dovrai lanciare l'oggetto prima di accedere all'indicizzatore, ma funziona. –

-1

Cambia la tua implementazione generica di ...

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

Questo dice esplicitamente che 'questo' è che.

+0

con entrambi implementati esplicitamente, è necessario eseguire il cast dell'elenco per utilizzarne uno, che non è quello che vuole. vuole default su quello generico e nascondere quello non generico. – Lucas

2

Questa è una vittima di my question here

Per riassumere, se si fa questo, si risolve il problema:

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