2015-04-12 19 views
6

Per ogni *Collection (HtmlNodeCollection, TreeNodeCollection, CookieCollection ecc) un'istanza di classe che ho bisogno di passare a un metodo che accetta solo una matrice o un elenco (non dovrebbe avere un metodo che accetta un TreeNodeCollection nel TreeView per esempio?) Ho scrivere un'estensione a metodo come questo:Modo rapido per convertire una raccolta in serie o lista?

public static TreeNode[] ToArray(this TreeNodeCollection nodes) 
     { 
      TreeNode[] arr = new TreeNode[nodes.Count]; 
      nodes.CopyTo(arr, 0); 
      return arr; 
     } 

Oppure un loop nella raccolta completa aggiungendo gli articoli al un'uscita lista e quindi convertire l'output-elenco in un array:

public static TreeNode[] ToArray(this TreeNodeCollection nodes) 
     { 
     var output = new List<TreeNode>(); 
      foreach (TreeNode node in nodes) 
       output.Nodes(node); 
      return output.ToArray(); 
} 

Quindi, la mia domanda è: Ho spesso bisogno di questi metodi di estensione. Può allocare molta memoria se la lista è grande, come di solito. Perché non è possibile ottenere un riferimento (non copiare) nell'array interno utilizzato da queste classi *Collection in modo da non dover utilizzare tali estensioni e eseguire questa allocazione di memoria? o persino fornire un metodo ToArray(). Non abbiamo bisogno di conoscere la sua implementazione interna o la matrice utilizzata in quest'ultimo caso.

+5

'Ho bisogno di passare a un metodo che accetta solo un array o elenco' Perché non' IEnumerable '? Puoi facilmente passare 'treeNodeCollection.Cast ()' per es. – EZI

+3

Utilizzare 'IEnumerable '. Se hai bisogno dell'array, usa 'collection.Cast () .ToArray()' e sbarazzati completamente dei tuoi metodi di estensione. –

+0

'.Cast <>()' veramente bello ... fa 'collection.Cast () .ToArray()' differisce dalla mia estensione '.ToArray()' (a parte il fatto che è nativo, ovviamente)? – Jack

risposta

10

La ragione per cui tutte le classi di raccolta BCL nascondono il loro array interno è per ragioni di "gradevolezza dell'API". L'array interno può cambiare nel caso in cui debba crescere o ridursi. Quindi, qualsiasi codice utente che abbia un riferimento al vecchio array può confondersi. Inoltre, il codice utente potrebbe accedere a indici di array non validi per l'accesso alla raccolta. Se si dispone di un List con Capacity = 16 && Count == 10 e quindi è possibile accedere alla matrice interna all'indice 15 che l'elenco non consentirebbe normalmente.

Questi problemi rendono l'API difficile da utilizzare. Causano ticket di supporto e domande Stack Overflow.

Eliminare il codice esistente e sostituirla con:

TreeNodeCollection nodes; 
var myArray = nodes.Cast<TreeNode>().ToArray(); 

Si può fare questo in un metodo di estensione se si sente il bisogno. Digitare il parametro come IEnumerable (non generici). Per me è un mistero il motivo per cui le collezioni esistenti nel BCL non sono state aggiornate per implementare IEnumerable<T>. Ecco perché è necessario il Case. I just created a User Voice item for this.

Problemi correlati