2011-08-29 4 views
2

Comment est-il possible que ReadOnlyCollection implémente IList? Ce dernier nécessite l'implémentation de la méthode Add, et ReadOnlyCollection ne l'implémente pas. Cependant, ReadOnlyCollection est concrète et peut être instancié ...Question sur les interfaces

Modifier

Le code suivant ne compile pas sur ma machine:

static void Main(string[] args) 
{ 
    List<string> people = new List<string>(){ 
     "Sidney", 
     "Jim", 
     "Bob"}; 

    ReadOnlyCollection<string> readOnlyPeople = new ReadOnlyCollection<string>(people); 
    readOnlyPeople.Add("Frank"); 
} 

L'appel à "Ajouter" dans la dernière déclaration est maintenant souligné en bleu dans Visual Studio 2010.

+1

Ce code ne sera pas compilé car la méthode 'Add' est implicitement implémentée. Vous devez lancer 'IList' avant de pouvoir y accéder. –

+0

Je suis toujours confus. Où est-il «explicitement» mis en œuvre? Je pensais que les interfaces ne supportaient pas les implémentations de méthodes ... – Andrew

+1

Vous avez raison de dire que les interfaces n'implémentent pas elles-mêmes la méthode. La mise en œuvre explicite est une chose spéciale en C# - [voir cette réponse pour plus d'informations] (http://stackoverflow.com/questions/143405/c-interfaces-implicit-and-explicit-implementation). –

Répondre

4

Il met en œuvre Ajouter, l'implémentation lance simplement un NotSupportedException.

L'implémentation utilise "explicit interface implementation", qui est un moyen d'implémenter des interfaces sans exposer directement les méthodes d'interface en tant que public sur la classe d'implémentation. C'est très utile quand vous avez une classe qui implémente plus d'une interface qui définit le même membre (voir l'exemple sur le lien). Au fond, il ressemble à ceci:

public interface IList<T> 
{ 
    int Add(object value); 
    // and a whole bunch of other stuff... 
} 

public class ReadOnlyCollection<T> : IList<T> 
{ 
    int IList<T>.Add(object value) 
    { 
     throw new NotSupportedException(); 
    } 
} 

Remarquez comment la méthode d'ajout n'est pas publique, donc si vous avez une instance de ReadOnlyCollection<T>, vous ne pouvez pas appeler directement Add sur elle. Ce que vous pouvez faire cependant, si vous voulez voir l'exception, est jeté votre instance à l'interface:

ReadOnlyCollection<string> readOnlyPeople = new ReadOnlyCollection<string>(people); 
((IList<string>)readonlyPeople).Add("Frank"); // <-- bang! 

L'autre façon, vous pouvez y parvenir est de déclarer votre variable comme directement IList<T>:

IList<string> readOnlyPeople = new ReadOnlyCollection<string>(people); 
readOnlyPeople.Add("Frank"); // <-- this should go 'bang!' too 
+0

Merci pour l'explication Jon. Je pensais que je devenais fou, sinon :) – Andrew