Arasındaki fark nedir IEnumerableve Array?
Arasındaki fark nedir IListve List?
Bunların işlevi aynı görünüyor.
Yanıtlar:
IEnumerable yalnızca minimum "yinelenebilir" işlevsellik sağlar. Sırayı geçebilirsiniz, ama bununla ilgili. Bunun dezavantajları vardır - örneğin, öğeleri IEnumerable kullanarak saymak veya n'inci öğeyi almak çok verimsizdir - ancak avantajları da vardır - örneğin, bir IEnumerable, asalların dizisi gibi sonsuz bir dizi olabilir.
Dizi, rastgele erişime sahip sabit boyutlu bir koleksiyondur (yani dizine dizine ekleyebilirsiniz).
Liste, rastgele erişimli değişken boyutlu bir koleksiyondur (yani öğeleri ekleyebilir ve kaldırabilirsiniz).
IList; List, BindingList, ObservableCollection, vb. Gibi çeşitli somut sınıflardan uzakta liste işlevselliğini (sayma, ekleme, kaldırma, dizinleyici erişimi) özetleyen bir arayüzdür.
IEnumerable, bir öğe koleksiyonu aracılığıyla yinelemeye izin veren bir arabirimdir (örneğin, foreach anahtar sözcüğü aracılığıyla).
Bir dizi .NET içseldir. Aynı türden öğeleri tutar, ancak sabit boyuttadır. X elemanlı bir dizi oluşturduğunuzda, büyüyemez veya küçülmez.
IList, bir liste için arabirimi tanımlar ve ayrıca IEnumerable'ı uygular.
List, IList arayüzünü uygular; somut bir liste türüdür.
.NET Listeleri ile diziler arasındaki fark, listelerin kendilerine eklenmiş elemanlara sahip olabilmesidir - bunlar, gerekli tüm öğeleri tutacak kadar büyür. Liste bunu dahili olarak bir dizide depolar ve dizi artık tüm öğeleri tutacak kadar büyük olmadığında, yeni bir dizi oluşturulur ve öğeler arasında kopyalanır.
IList ve dizilerin her ikisi de IEnumerable uygular. Arayüzler böyle çalışır - sınıflar sözleşmeyi uygular ve benzer şekilde davranır ve sonuç olarak benzer şekilde ele alınabilir (sınıfın IEnumerable'ı uyguladığını bilirsiniz, nasıl veya nedenlerini bilmenize gerek yoktur). Arayüzler hakkında okumanı öneririm.
IEnumerable ve IList arabirimlerdir . Dizi ve Liste sınıflardır. Dizi, IEnumerable'ı uygular. List, IEnumerable'ı genişleten IList'i uygular.
Düzenleme: itowlson'ın bir yorumda bahsettiği gibi, Array ayrıca IList'i de uygular.
IEnumerable koleksiyonunun oluşturulması tembeldir. Misal:
public IEnumerable<int> GetTwoInts()
{
yield return 1;
yield return 2;
}
public void Something()
{
var twoInts = GetTwoInts();
}
Yöntemde Bir şey GetTwoInts () çağrısı aslında GetTwoInts yönteminin çalıştırılmasına neden olmaz, çünkü numaralandırma hiçbir zaman yinelenmez.
twoIntsbir foreachveya çağrı koydu twoInts.ToList().
IEnumerablegibi birçok sınıflar tarafından kullanılan bir genel amaçlı arayüz Array, Listve Stringbir koleksiyonu üzerinde birisi iterate izin için. Temel olarak, foreachifadeyi yönlendiren şey budur .
IListtipik olarak türdeki değişkenleri Listson kullanıcılara nasıl sunduğunuzdur . Bu arabirim, temel koleksiyona rastgele erişime izin verir.
Diğer cevapları tamamlamak için, bir foreach ifadesi yürütürken ve arasında bir performans farkı olduğuna dikkat edin .IList<T>List<T>
Bunun nedeni, tarafından döndürülen yineleyici nesnenin List<T>.GetEnumeratorbir değer türü, döndüren nesnenin IList<T>.GetEnumeratorise bir başvuru türü olması ve dolayısıyla bir bellek ayırma gerektirmesidir (bkz . C # listesinin değer türünün Numaralandırıcısı ).
Bana göre IList<T>zaten çok iyi bir arayüz değil. Örneğin çağrı Addatabilir (bkz. Neden dizi IList uygular? ). Kapsüllemeye ihtiyacınız varsa IEnumerable<T>veya kullanmanız daha iyi olur IReadOnlyList<T>.
Diğer yanıtlara ek olarak, LINQ kullanırken Numaralandırılabilir ve Liste / Dizi arasındaki farklılığı anlamak, performansı büyük ölçüde etkileyebilir. Kısacası, Numaralandırılabilir bir sorgu oluşturucu olarak algılanabilirken, Liste / Dizi sorgunun sonucudur.
EntityFramework kullanan LINQ to SQL bağlamında, birincisi yalnızca SQL sorgusunu veritabanına karşı yürütmeden veya belleğe herhangi bir veri yüklemeden, daha sonra ise tersi oluşturmadan oluşturur. Bu yüzden .ToList(), iş mantığını gerçekleştirmek için hafızada ihtiyacımız olana kadar aramayı erteledik .
Diğer bağlamda, IEnumerable döndüren LINQ ifadesi .ToList(), çağrılana kadar yürütmeyi erteleyecektir . Aşağıdaki örneği düşünün:
void Main()
{
var w1 = "AB".AsEnumerable();
Console.WriteLine($"W1: 1");
w1 = w1.Where(W1);
Console.WriteLine($"W1: 2");
w1 = w1.Where(W2);
Console.WriteLine($"W1: 3");
w1.ToList();
Console.WriteLine($"----------");
var w2 = "CD".AsEnumerable();
Console.WriteLine($"W2: 1");
w2 = w2.Where(W1);
Console.WriteLine($"W2: 2");
w2 = w2.ToList();
Console.WriteLine($"W2: 3");
w2 = w2.Where(W2);
Console.WriteLine($"W2: 4");
w2.ToList();
Console.WriteLine($"----------");
}
bool W1(char arg)
{
Console.WriteLine($"W1:{arg}");
return true;
}
bool W2(char arg)
{
Console.WriteLine($"W2:{arg}");
return true;
}
OUTPUT:
W1: 1
W1: 2
W1: 3
W1:A
W2:A
W1:B
W2:B
----------
W2: 1
W2: 2
W1:C
W1:D
W2: 3
W2: 4
W2:C
W2:D
----------
İlk örnekte, ikisi .Where()"eklenir" ve sonunda .ToList()" A " öğesi önce borudan geçip sonra " B " öğesi ile çağrıldığında , dolayısıyla çıktıda " AABB " görülürken, ikinci örnekte birlikte yürütülür. .Where()diyoruz eğer her zaman çalıştırılır .ToList()dolayısıyla "görerek, hemen ardından CD " ve ardından " CD çıkışı iki kez tekrar". Bu nedenle, bir Numaralandırılabilir Listeye veya Diziye her dönüştürüldüğünde , koleksiyon büyük olduğunda performansa etki edecek olan koleksiyondaki tüm öğeler üzerinde bir O (n) yineleme maliyeti olacaktır.
.ToList()LINQ çağrıları arasında bu şekilde kod yazma eğiliminde olmasak da, kodu List/Arrayyerine geri dönen yeniden kullanılabilir yöntemlere dönüştürdüğümüzde bu daha sık gerçekleşecektir IEnumerable.
Ancak bu, her zaman devam etmemiz gerektiği anlamına gelmez IEnumerable. Towlson tarafından belirtildiği gibi, bu tür işlemler .Count()koleksiyon üzerinde yinelemeye neden olurken, bir Liste veya Dizi bu bilgiyi önceden hesaplayacak ve bu nedenle, birden çok kez List/Arrayarama yapmayı planlıyorsanız, dönüştürme daha verimli olacaktır .Count(). .CountListede, .Count()onu saymak için bir yöntem yerine bir özellik olmasının nedeni de budur .
Bu eski bir gönderi, ancak yine de yanıtlamayı düşünüyor. IEnumerable bir davranıştır, Array ise bir veri yapısıdır (Sabit boyutlu öğelerin bitişik koleksiyonu, öğelere dizinlerle erişmeyi kolaylaştırır). Bir Dizi IEnumerable uyguladığında, IEnumerable doğasında bulunan özelliği de (koleksiyon üzerinde yinelemeyi kolaylaştırmak için) göstermesi beklenir.