Neden çok sayıda / bir-çok ilişkide IEnumerable veya List <T> değil ICollection kullanıyorsunuz?


359

Gezinme özellikleri ile öğreticilerde bunu çok görüyorum ICollection<T> .

Bu, Varlık Çerçevesi için zorunlu bir gereklilik mi? KullanabilirmiyimIEnumerable ?

Veya ICollectionyerine kullanmanın temel amacı nedir ?IEnumerableList<T>

Yanıtlar:


440

Genellikle ne seçtiğiniz, hangi yöntemlere erişmeniz gerektiğine bağlı olacaktır. Genel olarak - IEnumerable<>(MSDN: http://msdn.microsoft.com/en-us/library/system.collections.ienumerable.aspx ) yalnızca yinelenmesi gereken nesnelerin listesi için, ICollection<>(MSDN: http: // msdn.microsoft.com/en-us/library/92t2ye13.aspx ) üzerinden yinelenmesi ve değiştirilmesi List<>gereken nesnelerin listesi, üzerinden yinelenmesi, değiştirilmesi, sıralanması vb. gereken nesnelerin listesi için (Buraya bakın tam liste için: http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx ).

Daha spesifik bir bakış açısıyla, tembel yükleme türü seçerek oynamak için geliyor. Varsayılan olarak, Entity Framework'teki gezinme özellikleri değişiklik izlemeyle birlikte gelir ve proxy'lerdir. Dinamik proxy'nin bir gezinme özelliği olarak oluşturulması için sanal türün uygulanması gerekirICollection .

İlişkinin "çok" sonunu temsil eden bir navigasyon özelliğinin ICollection'ı uygulayan bir tür döndürmesi gerekir; burada T, ilişkinin diğer ucundaki nesnenin türüdür. - POCO Proxies MSDN Oluşturma Gereksinimleri

İlişkileri Tanımlama ve Yönetme Hakkında Daha Fazla Bilgi MSDN


2
yani, bununla birlikte, Listçok daha iyi olmalı, değil mi?
Jan Carlo Viray

3
@JanCarloViray - Çok kullanma eğilimindeyim List. En fazla ek yüke sahip olmasına rağmen, en fazla işlevselliği sağlar.
Travis J

1
Listeler, dizinleyicileri tarafından bunları sıralama yeteneğinden daha fazla tanımlanır (bir tamsayı dizinleyicisine sahip olmak bir şeyi sıralamayı kolaylaştırır, ancak bu bir gereklilik değildir).
phoog

2
Düzenlemenizle ilgili olarak, bir özelliği arayüz türüyle sınırlamak bellekle değil kapsülleme ile ilgilidir. private IEnumerable<int> _integers = new List<int> { 1, 2, 3 };private List<int> _integers = new List<int> { 1, 2, 3 };
Şunu

13
@TravisJ: Değişken bir yapı türü döndüren uygulamasından ayrı List<T>bir GetEnumerator()yönteme sahiptir . Çoğu bağlamda, bu tür bağımsız bir yığın nesnesinden biraz daha iyi performans sağlar. Ördek türü sayıcıların (hem C # hem de vb.net yaptığı gibi) kod oluştururken bundan yararlanabilir . Eğer artığını önce , yöntem optimizasyonu imkansız hale bir yığın-tahsis nesneyi dönecektir. IEnumerable<T>List<T>.EnumeratorforeachList<T>IEnumrable<T>foreachIEnumerable<T>.GetEnumerator()
supercat

86

ICollection<T>IEnumerable<T>arayüz öğe eklemek, öğe kaldırmak veya koleksiyonu başka bir şekilde değiştirmek için hiçbir yol sağlamadığından kullanılır .


3
List <T> ile karşılaştırmaya ne dersiniz?
Jan Carlo Viray

12
List<T>uygular ICollection<T>.
harcayan

Jenerik olmayan ICollection, öğe eklemek için herhangi bir şekilde izin vermez, ancak yine de yararlı bir yardımcıdır, IEnumerable<T>çünkü Countgenellikle her şeyi numaralandırmadan çok daha hızlı bir üye sağlar . Bir IList<Cat>veya ICollection<Cat>, bir kod beklemeye geçirilirse IEnumerable<Animal>, Count()genişletme yönteminin, genel olmayan uygularsa hızlı olacağını ICollection, ancak tipik bir ICollection<Cat>uygulama yapılmayacağından yalnızca genel arabirimleri uyguladığında olmayacağını unutmayın ICollection<Animal>.
supercat

58

Şununla ilgili sorunuza yanıt verin List<T>:

List<T>bir sınıf; bir arabirim belirtmek uygulamada daha fazla esneklik sağlar. Daha iyi bir soru "neden olmasın IList<T>?"

Bu soruyu cevaplamak için neyin IList<T>eklediğini düşünün ICollection<T>: tamsayı indeksleme, bu da öğelerin keyfi bir sıraya sahip olduğu ve bu sıraya referansla alınabileceği anlamına gelir. Muhtemelen çoğu durumda anlamlı değildir, çünkü öğelerin muhtemelen farklı bağlamlarda farklı şekilde sipariş edilmesi gerekir.


21

ICollection ve IEnumerable arasında bazı temel farklar var

  • IEnumerable - Numaralandırıcıyı almak için yalnızca GetEnumerator yöntemini içerir ve döngüye izin verir
  • ICollection ek yöntemler içerir: Ekle, Kaldır, İçerir, Say, Kopyala
  • ıcollection IEnumerable'dan devralındı
  • ICollection ile toplama / kaldırma gibi yöntemleri kullanarak koleksiyonu değiştirebilirsiniz. IEnumerable ile aynı şeyi yapma özgürlüğünüz yok.

Basit Program:

using System;
using System.Collections;
using System.Collections.Generic;

namespace StackDemo
{
    class Program 
    {
        static void Main(string[] args)
        {
            List<Person> persons = new List<Person>();
            persons.Add(new Person("John",30));
            persons.Add(new Person("Jack", 27));

            ICollection<Person> personCollection = persons;
            IEnumerable<Person> personEnumeration = persons;

            // IEnumeration
            // IEnumration Contains only GetEnumerator method to get Enumerator and make a looping
            foreach (Person p in personEnumeration)
            {                                   
               Console.WriteLine("Name:{0}, Age:{1}", p.Name, p.Age);
            }

            // ICollection
            // ICollection Add/Remove/Contains/Count/CopyTo
            // ICollection is inherited from IEnumerable
            personCollection.Add(new Person("Tim", 10));

            foreach (Person p in personCollection)
            {
                Console.WriteLine("Name:{0}, Age:{1}", p.Name, p.Age);        
            }
            Console.ReadLine();

        }
    }

    class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public Person(string name, int age)
        {
            this.Name = name;
            this.Age = age;
        }
    }
}

13

Bu şekilde hatırlıyorum:

  1. IEnumerable, bir koleksiyondaki değerleri okumayı ancak ona yazmamayı sağlayan bir yöntem GetEnumerator () yöntemine sahiptir. Numaralandırıcıyı kullanmanın karmaşıklığının çoğu, C # 'daki her ifade için bizim tarafımızdan halledilir. IEnumerable bir özelliğe sahiptir: Current, geçerli öğeyi döndürür.

  2. ICollection IEnumerable uygular ve en çok kullanımı Count olan birkaç ek özellik ekler. ICollection uygulamasının genel sürümü Add () ve Remove () yöntemlerini uygular.

  3. IList hem IEnumerable hem de ICollection öğesini uygular ve öğelere tamsayı indeksleme erişimi ekler (sipariş veritabanında yapıldığından genellikle gerekli değildir).


4
Yazdıklarınıza dayanarak ICollection ve IList aynı. Lütfen, ICollection'da bulunmayan IList'e eklenenleri ekleyin.
bahisler

ICollection VS IList, IEnumerable ve ICollection ve ek işlevlerin tüm işlevlerini içeren System.Collection içinde yalnızca IList arabirimi. IList, Ekle ve Kaldır yöntemlerine sahiptir. Her iki yöntem de parametrelerinde dizini kabul eder. Böylece, toplama üzerinden dizin tabanlı işlemleri destekler.
E.Meir

7

Temel kullanım fikri, ICollectionsınırlı miktarda veriye salt erişim için bir arayüz sağlamaktır. Aslında bir ICollection.Count özelliğiniz var. IEnumerablemantıksal bir noktaya kadar okuduğunuz bazı veri zincirleri için daha uygundur, bazı durumlar özellikle tüketici tarafından veya numaralandırmanın sonuna kadar belirtilir.


14
Salt ICollectionokunur iken TIL ICollection<T>değildir.
Carl G

2

Gezinme özellikleri genellikle tembel yükleme gibi belirli Entity Framework işlevlerinden yararlanabilmeleri için sanal olarak tanımlanır.

Bir navigation özelliği birden çok varlığı (çoktan çoğa veya birden çoğa ilişkilerinde olduğu gibi) tutabilirse, türü ICollection gibi girdilerin eklenebileceği, silinebileceği ve güncellenebileceği bir liste olmalıdır.

https://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/creating-an-entity-framework-data-model-for-an-asp-net- mVC uygulama


2

Ben de ne yaptım geçmiş isimli kullanarak içimdeki sınıf koleksiyonları beyan IList<Class>, ICollection<Class>ya IEnumerable<Class>: Ben Depodaki bir yöntemde aşağıdaki herhangi bir sayıda yapmak zorunda kalacaktır olup olmadığına bağlı olarak (statik listede varsa) numaralandırmak, sıralama / sipariş veya değiştirme . Ben sadece nesneler üzerinde numaralandırmak (ve belki sıralamak) gerektiğinde o zaman List<Class>bir IEnumerable yöntemi içinde koleksiyonu ile çalışmak için bir sıcaklık oluşturun . Bu uygulamanın sadece koleksiyon nispeten küçükse etkili olacağını düşünüyorum, ancak genel olarak iyi bir uygulama olabilir, idk. Bunun neden iyi bir uygulama olmayacağına dair kanıt varsa lütfen beni düzeltin.


0

Kutunun dışında / mantığı ile düşünmeyi deneyelim ve sorunuzdaki şu üç arayüzü net bir şekilde anlayalım:

Bazı örneklerin sınıfı System.Collection.IEnumerable arabirimini uyguladığında, basit bir deyişle, bu örneğin hem numaralandırılabilir hem de yinelenebilir olduğunu söyleyebiliriz, yani bu örnek tek bir döngüde bir şekilde git / al / geç / bu örneğin içerdiği tüm öğelerin ve öğelerin üzerinde gezinin / yineleyin.

Bu, bu örneğin içerdiği tüm öğeleri ve öğeleri numaralandırmak için de mümkün olduğu anlamına gelir.

System.Collection.IEnumerable arabirimini uygulayan her sınıf, bağımsız değişken almayan ve bir System.Collections.IEnumerator örneği döndüren GetEnumerator yöntemini de uygular.

System.Collections.IEnumerator arabiriminin örnekleri, C ++ yineleyicilerine çok benzer davranır.

Bazı örneklerin sınıfı System.Collection.ICollection arabirimini uyguladığında, basit bir ifadeyle, bu örneğin bir şeyler koleksiyonu olduğunu söyleyebiliriz.

Bu arabirimin genel sürümü, yani System.Collection.Generic.ICollection, daha bilgilendiricidir çünkü bu genel arabirim, koleksiyondaki öğelerin türünün ne olduğunu açıkça belirtir.

Tüm bunlar makul, rasyonel, mantıklı ve System.Collections.ICollection arayüzünün System.Collections.Inumerable arayüzünden devralınması mantıklı. her koleksiyonda.

System.Collections.ICollection arabirimi değiştirilebilir sonlu bir dinamik koleksiyonu temsil eder; bu, var olan öğelerin koleksiyondan kaldırılabileceği ve aynı koleksiyona yeni öğeler eklenebileceği anlamına gelir.

Bu, System.Collections.ICollection arabiriminin neden "Ekle" ve "Kaldır" yöntemlerine sahip olduğunu açıklar.

System.Collections.ICollection arabiriminin bu örnekleri sonlu koleksiyonlar olduğu için "sonlu" kelimesi, bu arabirimin her koleksiyonunda her zaman sonlu sayıda öğe ve öğe bulunduğunu gösterir.

Count System.Collections.ICollection arabirimi özelliğinin bu sayıyı döndüreceğini varsayar.

System.Collections.IEnumerable arabirimi, System.Collections.ICollection arabiriminin sahip olduğu bu yöntemlere ve özelliklere sahip değildir, çünkü System.Collections.IEnumerable'ın System.Collections.ICollection arabiriminin sahip olduğu bu yöntemlere ve özelliklere sahip olması mantıklı değildir.

Mantık aynı zamanda hem numaralandırılabilir hem de yinelenebilir olan her örneğin mutlaka bir koleksiyon olmadığını ve mutlaka değiştirilemeyeceğini söylüyor.

Değişken dediğimde, derhal hem numaralandırılabilir hem de yinelenebilir bir şey ekleyip çıkarabileceğinizi hemen düşünmeyin.

Örneğin, asal sayıların sonlu bir dizisini oluşturduysam, bu asal sayıların sonlu dizisi gerçekten de System.Collections.Inumerable arabiriminin bir örneğidir, çünkü şimdi bu sonlu dizideki tüm asal sayıları tek bir döngüde ele alabilirim ve her birini konsol penceresine veya ekrana yazdırmak gibi her ne yapmak istediğimi yapıyorum, ancak bu asal sayıların sonlu sırası System.Collections.ICollection arabiriminin bir örneği değil, çünkü bu mantıklı değil asal sayıların bu sonlu sırasına bileşik sayılar ekleyin.

Ayrıca bir sonraki yinelemede, geçerli yinelemedeki geçerli asal sayıya bir sonraki en yakın asal sayıyı elde etmek istersiniz, eğer öyleyse, bu asal sayıların sonlu sekansından mevcut asal sayıları da kaldırmak istemezsiniz.

Ayrıca muhtemelen kullanmak, kodlamak ve System.Collections.Inumerable arabirimi "verim dönüş" yazmak ve asal sayılar üretmek ve bellek yığın üzerinde bir şey tahsis ve sonra her ikisi için Çöp Toplayıcı (GC) görev istiyorum Bu hafızayı yığından ayırın ve boşaltın, çünkü bu hem işletim sistemi belleğinin israfıdır hem de performansı düşürür.

System.Collections.ICollection arabiriminin yöntemleri ve özellikleri çağrılırken öbek üzerinde dinamik bellek ayırma ve ayırma yapılmalıdır, ancak System.Collections.Inumerable arabirimi (System.Collections.Ilumerable arabirimi yalnızca 1 yöntem ve 0 özellik).

Bu Yığın Taşması web sayfasında başkalarının söylediklerine göre, System.Collections.IList arabirimi basitçe düzenlenebilir bir koleksiyonu ve bu, System.Collections.IList arabiriminin yöntemlerinin System.Collections.ICollection arabiriminin aksine neden dizinlerle çalıştığını açıklar.

Kısacası System.Collections.ICollection arabirimi bunun bir örneğinin düzenlenebilir olduğu anlamına gelmez, ancak System.Collections.IList arabirimi bunu ima eder.

Teorik olarak sıralı set, sırasız setin özel durumudur.

Bu aynı zamanda anlamlıdır ve System.Collections.IList arabiriminin neden System.Collections.ICollection arabirimini devraldığını açıklar.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.