J'ai des méthodes qui retournent des collections privées à l'appelant et je veux empêcher l'appelant de modifier les collections retournées.Comment empêcher un appelant de méthode de modifier une collection retournée?
private readonly Foo[] foos;
public IEnumerable<Foo> GetFoos()
{
return this.foos;
}
Au moment de la collection privée est un réseau fixe, mais à l'avenir la collection pourrait devenir une liste si la nécessité d'ajouter de nouveaux éléments au moment de l'exécution se fait sentir.
Il existe plusieurs solutions pour empêcher l'appelant de modifier la collection. Renvoyer IEnumerable<T>
est la solution la plus simple, mais l'appelant peut toujours convertir la valeur renvoyée en IList<T>
et modifier la collection. Le clonage des collections présente l'inconvénient évident qu'il existe deux collections qui peuvent évoluer indépendamment. Jusqu'à présent, j'ai considéré les options suivantes.
- Enveloppant la collection dans
ReadOnlyCollection<T>
. - Renvoyer l'un des itérateurs LINQ définis par la classe
Enumerable
en effectuant une projection fictive commelist.Select(item => item)
. En fait je considère utiliserWhere(item => true)
parce que l'itérateur retourné semble plus léger. - Ecriture d'un wrapper personnalisé.
Ce que je n'aime pas sur l'utilisation ReadOnlyCollection<T>
est qu'il met en œuvre IList<T>
et appelant Add()
ou l'accès à l'indexeur entraînera des exceptions. Bien que cela soit absolument correct en théorie, presque aucun vrai code ne vérifie IList<T>.IsReadOnly
ou IList<T>.IsFixedSize
. L'utilisation des itérateurs LINQ - J'ai enveloppé le code dans une méthode d'extension MakeReadOnly()
- empêche ce scénario, mais il a le goût d'un hack.
Écrire un emballage personnalisé? Réinventer la roue?
Des idées, des considérations ou d'autres solutions?
Bien que le marquage à cette question, j'ai découvert this Stack Overflow question je n'ai pas remarqué avant. Jon Skeet suggère d'utiliser le "LINQ hack", mais encore plus efficace en utilisant Skip(0)
.
À moins qu'il y ait des problèmes de sécurité (appelants potentiellement hostiles), je ne m'inquiète généralement pas de la protection contre le lancement imprudent ou l'appel Add sur un ReadOnlyCollection. Les développeurs stupides peuvent également utiliser des éléments internes de réflexion et d'accès. Il est difficile de rendre le code idiot. L'objectif est de protéger contre l'utilisation innocente de l'interface publique. – TrueWill