2015-04-12 15 views
6

her *Collection (HtmlNodeCollection, TreeNodeCollection, CookieCollection vs.) yalnızca bir dizi veya liste kabul eden bir yönteme geçmesi gereken sınıf örneği (örneğin TreeView bir TreeNodeCollection kabul eden bir yöntem olmamalıdır?) Ben böyle bir uzantı-yöntemi yazmaya:Bir Koleksiyonu Array veya Listeye dönüştürmenin hızlı yolu? Için

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

Veya tüm koleksiyondan bir çıkış-listeye öğe ekleyerek ve daha sonra bir diziye çıkış listesine dönüştürme üzerinde döngü:

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

Yani, sorum şu: Sık sık bu uzantı yöntemlerine ihtiyacım var. Genelde olduğu gibi liste büyükse çok fazla bellek ayırabilir. Neden bu *Collection sınıfları tarafından kullanılan iç diziye bir başvuru (kopya değil) alamıyorum, bu nedenle bu uzantıları kullanmam ve bu bellek ayırmalarını kullanmam gerekmedi? hatta bir ToArray() yöntemini sağlar. Bu son durumda kullanılan iç uygulamasını veya dizisini bilmemize gerek yok.

+5

'Yalnızca bir diziyi veya listeyi kabul eden bir yönteme geçmem gerekiyor 'IEnumerable '? Ex için treeNodeCollection.Cast () 'öğesini kolayca geçirebilirsiniz. – EZI

+3

IEnumerable 'kullanın. Eğer diziye ihtiyacınız varsa, "collection.Cast () .ToArray()' ı kullanın ve uzantı yöntemlerinden tamamen kurtulun. –

+0

'.Cast <>()' gerçekten güzel ... does 'collection.Cast () .ToArray()' '.ToArray()' uzantısından farklıdır (tabii ki gerçek olduğu gerçeğinden ayrı olarak)? – Jack

cevap

10

Tüm BCL koleksiyon sınıflarının iç dizisini gizlemesinin nedeni "API inceliği" nedenlerinden kaynaklanmaktadır. Dahili dizi büyümesi veya küçültülmesi gerektiğinde değişebilir. Daha sonra, eski diziye referans veren herhangi bir kullanıcı kodu karışabilir. Ayrıca, kullanıcı kodu, koleksiyona erişim için geçersiz olan dizi dizinlerine erişebilir. List, Capacity = 16 && Count == 10 ile varsa ve daha sonra listenin normal olarak izin vermediği dizin 15'te dahili diziye erişebilirsiniz.

Bu sorunlar, API'nin kullanımını zorlaştırır. Destek biletlerine ve Yığın Taşması sorularına neden oluyorlar.

varolan kodu silin ve ile değiştirin: Bunu ihtiyacını düşünüyorsanız bir uzantısı yöntem haline bu yapabilirsiniz

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

. Parametreyi IEnumerable (jenerik yok) olarak yazın. BCL'deki mevcut koleksiyonların neden IEnumerable<T>'u uygulamak için yükseltilmediğine dair bir gizem. Bu yüzden Case'a ihtiyacınız var. I just created a User Voice item for this.

İlgili konular