MyClass[] array;
List<MyClass> list;
Biri diğerine tercih edildiğinde senaryolar nelerdir? Ve neden?
MyClass[] array;
List<MyClass> list;
Biri diğerine tercih edildiğinde senaryolar nelerdir? Ve neden?
Yanıtlar:
Gerçekte, bir dizi kullanmak istemeniz nadirdir. List<T>
Dizileri yeniden boyutlandırmak pahalı olduğundan, kesinlikle veri eklemek / kaldırmak istediğiniz herhangi bir zamanda kullanın . Verilerin sabit uzunlukta olduğunu biliyorsanız ve çok özel bir nedenden dolayı (kıyaslamadan sonra) mikro optimizasyon yapmak istiyorsanız , bir dizi yararlı olabilir.
List<T>
bir diziden çok daha fazla işlevsellik sunar (LINQ onu biraz geliştirse de) ve neredeyse her zaman doğru seçimdir. params
Elbette argümanlar hariç . ;-p
Bir sayaç olarak - List<T>
tek boyutludur; nerede-gibi dikdörtgen (vb.) dizileriniz olduğu gibi - int[,]
veya string[,,]
bir nesne modelinde bu tür verileri (gerekirse) modellemenin başka yolları da vardır.
Ayrıca bakınız:
Bununla birlikte, protobuf-net projemde çok fazla dizi kullanıyorum ; tamamen performans için:
byte[]
kodlama için oldukça önemlidir;byte[]
Temel akışa (ve vv) göndermeden önce doldurduğum yerel bir yuvarlanma tamponu kullanıyorum ; BufferedStream
vs daha hızlı ;Foo[]
yerine List<Foo>
) kullanır .Ancak bu kesinlikle bir istisnadır; genel iş kolu işleme için List<T>
her seferinde kazanır.
Gerçekten sadece şaşırdım bir bağlantı eklemek için cevap henüz belirtilmedi: Eric's Lippert'in "Diziler biraz zararlı olarak kabul edildi " adlı blog girişi .
Koleksiyonların pratik olduğu her yerde kullanılmasını önerdiği başlıktan karar verebilirsiniz - ancak Marc'ın haklı olarak işaret ettiği gibi, bir dizinin gerçekten tek pratik çözüm olduğu birçok yer vardır.
Önerilen diğer yanıtlara bakılmaksızın, List<T>
işlem yaparken diziler kullanmak isteyeceksiniz:
List<T>
bayt dizisi yerine burada kullanmaktan ne bahseder ?
Performansla gerçekten ilgilenmiyorsanız ve bununla birlikte, "Neden C ++ yerine .Net kullanıyorsunuz?" Liste <> ile devam etmelisiniz. Bakımı daha kolaydır ve sizin için perde arkasında bir dizi yeniden boyutlandırma tüm kirli iş yapar. (Gerekirse, Liste <> dizi boyutlarını seçme konusunda oldukça zekidir, bu nedenle genellikle gerek yoktur.)
Diziler should koleksiyonu kendisinin değişmezlik istemcisi & sağlayıcı kodu (koleksiyon içindeki öğeler mutlaka değişmezlik) VE IEnumerable uygun olmadığında arasındaki sözleşmenin parçası olduğunda Listesine tercihi kullanılacak.
Örneğin,
var str = "This is a string";
var strChars = str.ToCharArray(); // returns array
"StrChars" modifikasyonunun orijinal "str" nesnesini değiştirmeyeceği açıktır, "str" nin altında yatan türden bağımsız olarak uygulama düzeyinde bilgi.
Ama varsayalım ki
var str = "This is a string";
var strChars = str.ToCharList(); // returns List<char>
strChars.Insert(0, 'X');
Bu durumda, insert yönteminin orijinal "str" nesnesini değiştirip değiştirmeyeceği tek başına bu kod snippet'inden anlaşılamaz. Sözleşme ile Tasarım yaklaşımını kıran bu belirlemeyi yapmak için String'in uygulama düzeyinde bilgisini gerektirir. String durumunda, bu büyük bir anlaşma değil, ancak hemen hemen her durumda büyük bir anlaşma olabilir. Listeyi salt okunur olarak ayarlamak yardımcı olur, ancak derleme zamanı değil çalışma zamanı hatalarıyla sonuçlanır.
To
olarak, orijinal örneği değiştirme yeteneği olmayan bir nesne oluşturacaktır strChars as char[]
.
str
dahili bir dizi kullanır ve ToCharArray
bu dizi için bir başvuru verir istemci mutasyona olabilir str
boyutu kalıntıları sabit olsa bile, bu dizinin elemanları değiştirerek. Ancak 'strChars' modifikasyonunun orijinal "str" nesnesini değiştirmeyeceği açıktır. Burada ne eksik? Gördüğüm kadarıyla, her iki durumda da müşteri iç temsile erişebilir ve türüne bakılmaksızın, bu bir tür mutasyona izin verir.
Çoğu zaman, bir kullanmak List
yeterlidir. A List
, verilerini işlemek için dahili bir dizi kullanır List
ve mevcut kapasitesinden daha fazla öğe eklerken diziyi otomatik olarak yeniden boyutlandırır , bu da kapasiteyi önceden bilmeniz gereken bir diziden daha kolay hale getirir.
Bkz. Http://msdn.microsoft.com/en-us/library/ms379570(v=vs.80).aspx#datastructures20_1_topic5C # 'daki Listeler hakkında daha fazla bilgi edinmek için veya yalnızca kaynak kodunu kullanın.System.Collections.Generic.List<T>
.
Çok boyutlu verilere ihtiyacınız varsa (örneğin bir matris veya grafik programlamada), muhtemelen bir array
bunun yerine .
Her zaman olduğu gibi, bellek veya performans bir sorunsa ölçün! Aksi takdirde kod hakkında yanlış varsayımlar yapabilirsiniz.
Diziler Vs. Listeler klasik bir sürdürülebilirlik ve performans sorunudur. Neredeyse tüm geliştiricilerin takip ettiği temel kural, her ikisi için de ateş etmeniz gerektiğidir, ancak çatışmalara girdiklerinde performans üzerinde sürdürülebilirliği seçin. Bu kuralın istisnası, performansın zaten bir sorun olduğunu kanıtlamış olmasıdır. Bu prensibi Arrays Vs. Listeler, sonra ne elde edersiniz:
Performans sorunlarına ulaşıncaya kadar güçlü yazılan listeler kullanın. Bir performans sorunuyla karşılaşırsanız, dizilere bırakmanın çözüm ile performans açısından çözümünüze bakım açısından çözümünüze zarar vereceğinden daha fazla fayda sağlayıp sağlayamayacağına karar verin.
Henüz bahsedilmeyen başka bir durum, her birinin birbirine yapışmış sabit bir grup ilişkili ancak bağımsız değişkenlerden oluşan çok sayıda öğeye sahip olacağıdır (örneğin bir noktanın koordinatları veya bir 3d üçgenin köşeleri). Bir dizi açık alan yapısı, elemanlarının verimli bir şekilde "yerinde" değiştirilmesine izin verecektir - diğer toplama türleriyle mümkün olmayan bir şey. Bir yapı dizisi elemanlarını ardışık olarak RAM'de tuttuğundan, dizi elemanlarına sıralı erişim çok hızlı olabilir. Kodun bir dizi boyunca birçok ardışık geçiş yapması gerektiği durumlarda, bir yapılar dizisi bir dizi veya sınıf nesnesi referanslarının diğer koleksiyonundan 2: 1 faktörüyle daha iyi performans gösterebilir; Daha ileri,
Diziler yeniden boyutlandırılamasa da, kullanımda olan öğelerin sayısıyla birlikte kodun bir dizi başvurusunu depolaması ve diziyi gerektiği gibi daha büyük bir diziyle değiştirmesi zor değildir. Alternatif olarak, çok benzer davranan, List<T>
ancak destek deposunu açığa çıkaran bir tür için kod kolayca yazılabilir , böylece ya MyPoints.Add(nextPoint);
ya söylenebilir MyPoints.Items[23].X += 5;
. Kod listenin sonunun ötesine erişmeye çalıştığında, ikincisinin mutlaka bir istisna atmayacağını, ancak kullanımın kavramsal olarak oldukça benzer olacağını unutmayın List<T>
.
Point[] arr;
, kodun söylenmesi mümkündür, örn arr[3].x+=q;
. Örneğin List<Point> list
, bunun yerine söylemek gerekir Point temp=list[3]; temp.x+=q; list[3]=temp;
. List<T>
Bir yöntem olsaydı faydalı olurdu Update<TP>(int index, ActionByRefRef<T,TP> proc, ref TP params)
. ve derleyiciler list[3].x+=q;
dönüşebilir {list.Update(3, (ref int value, ref int param)=>value+=param, ref q);
ancak böyle bir özellik yoktur.
list[0].X += 3;
listenin ilk öğesinin X özelliğine 3 ekler. Ve list
a List<Point>
ve Point
X ve Y özelliklerine sahip bir sınıftır
.NET'teki listeler diziler üzerindeki sarmalayıcılardır ve dahili olarak bir dizi kullanırlar. Listelerdeki işlemlerin zaman karmaşıklığı, dizilerle aynıdır, ancak listelerin tüm ek işlevselliği / kullanım kolaylığıyla (otomatik yeniden boyutlandırma ve liste sınıfıyla birlikte gelen yöntemler gibi) biraz daha fazla ek yük vardır. Oldukça, son derece optimize edilmiş kod yazmanız gerekiyorsa veya diziler etrafında inşa edilmiş diğer kodlarla çalışıyorsanız, bunu yapmamak için zorlayıcı bir neden olmadığı sürece her durumda listelerin kullanılmasını öneriyorum .
Her veri türünün özelliklerinin karşılaştırılmasından ziyade, en pragmatik cevap "özellikle ikisi de uyguladığından beri yapmanız gereken şey için farklılıklar muhtemelen o kadar önemli değil IEnumerable
, bu yüzden popüler sözleşmeyi takip edin ve bir List
bir sebep olmadan, muhtemelen bu noktada bir diziyi a List
.
Çoğu zaman yönetilen kodda koleksiyonların mikro optimizasyonlar hakkında endişelenmeyle mümkün olduğunca kolay çalışmasını tercih edersiniz.
Onlar popüler olmayabilir, ama ben oyun projelerinde Diziler hayranıyım. - Yineleme hızı bazı durumlarda önemli olabilir, bir Array üzerindeki her öğenin öğe başına fazla bir şey yapmıyorsanız önemli ölçüde daha az yükü vardır - Ekleme ve kaldırma yardımcı işlevlerle o kadar zor değildir - Daha yavaş, ancak yalnızca bir kez oluşturduğunuz durumlarda önemli olmayabilir - Çoğu durumda, daha az fazla bellek boşa harcanır (yalnızca yapı dizileri ile gerçekten önemlidir) - Biraz daha az çöp ve işaretçi ve işaretçi kovalaması
Bununla birlikte, Listeyi pratikte Dizilerden çok daha sık kullanıyorum, ama her birinin yeri var.
Liste, sarıcı ve numaralandırma yükünü optimize edebilmeleri için yerleşik bir türün olması iyi olurdu.
Liste doldurmak bir diziden daha kolaydır. Diziler için, verilerin tam uzunluğunu bilmeniz gerekir, ancak listeler için veri boyutu herhangi biri olabilir. Ve bir listeyi diziye dönüştürebilirsiniz.
List<URLDTO> urls = new List<URLDTO>();
urls.Add(new URLDTO() {
key = "wiki",
url = "https://...",
});
urls.Add(new URLDTO()
{
key = "url",
url = "http://...",
});
urls.Add(new URLDTO()
{
key = "dir",
url = "https://...",
});
// convert a list into an array: URLDTO[]
return urls.ToArray();
Kimse bahsetmediği için: C # 'da bir dizi bir listedir. MyClass[]
ve List<MyClass>
her ikisi de uygular IList<MyClass>
. (örneğin void Foo(IList<int> foo)
şöyle Foo(new[] { 1, 2, 3 })
veyaFoo(new List<int> { 1, 2, 3 })
)
Bu nedenle, a'yı List<MyClass>
bağımsız değişken olarak kabul eden ancak yalnızca özellik alt kümesini kullanan bir yöntem yazıyorsanız , şu şekilde bildirmek isteyebilirsiniz:IList<MyClass>
bunun yerine arayanların rahatlığı için .
Detaylar:
List
, sadece IList
arayüzü uygular .
Tamamen veri yapısının gerekli olduğu bağlamlara bağlıdır. Örneğin, Listeyi kullanarak diğer işlevler veya hizmetler tarafından kullanılacak öğeleri oluşturuyorsanız, bunu başarmanın mükemmel yoludur.
Şimdi bir öğe listeniz varsa ve bunları görüntülemek istiyorsanız, bir web sayfası dizisinde kullanmanız gereken kapsayıcı olduğunu söyleyin.
IEnumerable<T>
- o zaman onları tamponlamak yerine nesneleri akışı.
Yerinde döküm yapma yeteneğinden bahsetmeye değer.
interface IWork { }
class Foo : IWork { }
void Test( )
{
List<Foo> bb = new List<Foo>( );
// Error: CS0029 Cannot implicitly convert type 'System.Collections.Generic.List<Foo>' to 'System.Collections.Generic.List<IWork>'
List<IWork> cc = bb;
Foo[] bbb = new Foo[4];
// Fine
IWork[] ccc = bbb;
}
Dolayısıyla Array , dönüş türü veya işlevler için bağımsız değişkente kullanıldığında biraz daha esneklik sunar.
IWork[] GetAllWorks( )
{
List<Foo> fooWorks = new List<Foo>( );
return fooWorks.ToArray( ); // Fine
}
void ExecuteWorks( IWork[] works ) { } // Also accept Foo[]