web-dev-qa-db-fra.com

Quel est le meilleur moyen de créer un tableau en lecture seule en C #?

J'ai la situation extrêmement improbable et originale de vouloir retourner un tableau en lecture seule de ma propriété. Jusqu'à présent, je ne connais qu'une seule façon de le faire - à travers le System.Collections.ObjectModel.ReadOnlyCollection<T>. Mais cela me semble quelque peu gênant, sans oublier que cette classe perd la possibilité d'accéder aux éléments du tableau par leur index ( ajouté: oups, j'ai raté l'indexeur ). N'y a-t-il pas de meilleur moyen? Quelque chose qui pourrait rendre le tableau lui-même immuable?

43
Vilx-

Utilisez ReadOnlyCollection<T> . Il est en lecture seule et, contrairement à ce que vous croyez, il dispose d'un indexeur.

Les tableaux ne sont pas immuables et il n'y a aucun moyen de les créer sans utiliser un wrapper comme ReadOnlyCollection<T>.

Notez que la création d'un wrapper ReadOnlyCollection<T> est une opération O(1) et n'entraîne aucun coût de performance.

Mettre à jour
D'autres réponses ont suggéré de ne fonder que les collections sur le plus récent IReadOnlyList<T> , qui étend IReadOnlyCollection<T> pour ajouter un indexeur. Malheureusement, cela ne vous permet pas de contrôler la mutabilité de la collection, car celle-ci pourrait être renvoyée dans le type de collection d'origine et mutée.

Au lieu de cela, vous devriez toujours utiliser le ReadOnlyCollection<T> (la méthode List<T>AsReadOnly() , ou la méthode statique Arrays AsReadOnly() aide à envelopper les listes et les tableaux en conséquence) pour créer un accès immuable à la collection puis l'exposer directement ou comme l'une des interfaces qu'il prend en charge, y compris IReadOnlyList<T>.

45
Jeff Yates

.NET Framework 4.5 a introduit IReadOnlyList<T> qui s'étend de IReadOnlyCollection<T> en ajoutant T this[int index] { /*..*/ get; }

Vous pouvez convertir de T[] à IReadOnlyList<T>. Un avantage de ceci est que (IReadOnlyList<T>)array équivaut naturellement à array; aucune boxe n'est impliquée. 

Bien sûr, comme un wrapper n’est pas utilisé, (T[])GetReadOnlyList() serait mutable.

10
Warty

À partir de .NET Framework 2.0, vous trouverez Array.AsReadOnly qui crée automatiquement un wrapper ReadOnlyCollection pour vous.

6
N8allan

Si vous voulez vraiment un tableau retourné, mais craignez que le consommateur du tableau ne manipule les données internes, renvoyez simplement une copie du tableau. Personnellement, je pense toujours que ReadOnlyCollection<T> est la voie à suivre, mais si vousVRAIMENTvoulez un tableau .....

5
BFree

IEnumerable vient à l'esprit.

1
epitka

Vous voudrez peut-être implémenter l'interface IEnumerable et surcharger l'opérateur this [int] pour refuser l'accès à son setter

0
Morfildur

Il existe maintenant un support pour les collections immuables ..__ Voir https://www.nuget.org/packages/System.Collections.Immutable

Cela prend en charge l’un des éléments suivants:

  • .NET 4.5 (ou supérieur)
  • .NETStandard 1.0 (ou supérieur)
  • Windows 8.0
  • WindowsPhone 8.0
  • WindowsPhoneApp 8.1
  • Bibliothèque de classes portable (.NETFramework 4.5, Windows 8.0, WindowsPhone 8.0, WindowsPhoneApp 8.1)
0
Henry