2009-02-06 9 views
1

La méthode Add de l'interface ICollection(T) a été explicitement implémentée par la classe LinkedList(T)-. Cette collection a à la place des méthodes AddFirst et AddLast (entre autres). La méthode implémentée explicitement correspond à la méthode AddLast. Cela a quelques inconvénients et à mon humble avis aucun avantage du tout. Les deux principaux inconvénients sont les suivants:LinkedList (T) add-method

  1. Vous ne pouvez pas utiliser l'initialisation de collection sur une LinkedList (T) car elle nécessite une méthode Add-method.
  2. Si vous avez utilisé un List (T) dans une méthode et que vous voulez le modifier pour utiliser LinkedList (T), vous devrez mettre à jour tous les appels à Add pour appeler AddLast à la place.

La façon dont je pense à ce sujet est que vous devriez jamais mettre en œuvre explicitement les membres de l'interface à moins qu'ils ne font aucun sens quand vous connaissez le type de béton. Par exemple, la méthode Add devrait être explicitement implémentée (et effectivement cachée) si vous implémentez une ICollection (T) en lecture seule. Y at-il d'autres exemples de méthodes explicitement implémentées qui n'auraient pas dû figurer dans le framework?

En note: Pour résoudre le problème numéro 2, vous pouvez créer une méthode d'extension "Ajouter" pour la classe LinkedList (T).

Répondre

4

La méthode Add serait ambiguë, donc je suis content d'une implémentation explicite ...

Queue[<T>] et Stack[<T>] ont un comportement similaire.

Pour les autres membres explicites curieux (hors collection) - qu'en est-il de DbParameter.Precision et DbParameter.Scale. Pour ce qui est du transfert entre les deux, vous pouvez toujours écrire une méthode d'extension ToLinkedList<T> sur IEnumerable<T>.

alternative - une méthode d'extension AddRange<T> va un long chemin ...

static void Main() 
{ 
    var list = new LinkedList<int>(); 
    list.AddRange(1, 2, 3, 4, 5); 
} 
static void AddRange<T>(this ICollection<T> list, params T[] values) 
{ 
    foreach (T value in values) 
    { 
     list.Add(value); 
    } 
} 

(EDIT) Vous pouvez également utiliser une API « fluent » si vous voulez être en mesure de l'utiliser comme un seul expression:

static void Main() 
{ 
    var list = new LinkedList<int>().AddRange(1, 2, 3, 4, 5); 
    // `list` is correctly a LinkedList<int> here 
} 
static TCollection AddRange<TCollection, TValue>(
    this TCollection collection, params TValue[] values) 
    where TCollection : ICollection<TValue> 
{ 
    foreach (TValue value in values) 
    { 
     collection.Add(value); 
    } 
    return collection; 
} 
+0

Je suppose que vous voulez dire que ce serait ambigu pour le développeur? Le problème n'est pas que vous ne pouvez pas ajouter une plage, le problème est que l'interface diffère des autres ICollections de sorte qu'elles ne sont pas interchangeables à moins d'être castées dans l'interface. –

+0

Ce qui explique en grande partie pourquoi les interfaces existent ... ajouter à cette liste Queue and Stack, par exemple. –

+0

Les files d'attente et les piles ne sont pas sémantiquement comparables à des collections simples. La même chose pourrait être plus élégamment accomplie avec le EditorBrowsableAttribute. –

Questions connexes