많은 / 일대 다 관계에서 IEnumerable 또는 List <T>가 아닌 ICollection을 사용하는 이유는 무엇입니까?


359

내비게이션 속성이와 같은 자습서 에서이 내용을 많이 볼 수 ICollection<T>있습니다.

이것이 Entity Framework의 필수 요구 사항입니까? 사용할 수 있습니까 IEnumerable?

ICollection대신 IEnumerable또는 심지어 사용하는 주요 목적은 무엇입니까 List<T>?

답변:


439

일반적으로 선택하는 것은 액세스해야하는 방법에 따라 다릅니다. 일반적으로- IEnumerable<>(MSDN : http://msdn.microsoft.com/en-us/library/system.collections.ienumerable.aspx )를 통해 반복해야하는 개체 목록 ICollection<>(MSDN : http : // msdn.microsoft.com/ko-kr/library/92t2ye13.aspx )를 통해 반복 및 수정 List<>해야하는 개체 목록, 반복, 수정, 정렬 등을 수행해야하는 개체 목록 (여기 참조) 전체 목록 : http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx ).

보다 구체적인 관점에서, 유형 선택에 따라 지연 로딩이 발생합니다. 기본적으로 Entity Framework의 탐색 속성에는 변경 내용 추적 기능이 있으며 프록시입니다. 동적 프록시를 탐색 특성으로 작성하려면 가상 유형 구현 되어야 합니다 ICollection.

관계의 "많은"끝을 나타내는 탐색 속성은 ICollection을 구현하는 형식을 반환해야합니다. 여기서 T는 관계의 다른 쪽 끝에있는 개체의 형식입니다. - POCO 프록시 생성을위한 요구 사항 MSDN을

관계 정의 및 관리 MSDN 에 대한 추가 정보


2
그래서 그것 List으로 훨씬 나아 져야합니다
Jan Carlo Viray

3
@ JanCarloViray- List많이 사용 하는 경향이 있습니다 . 오버 헤드가 가장 많지만 가장 많은 기능을 제공합니다.
트래비스 J

1
목록은 정렬 기능보다 인덱서에 의해 더 많이 정의됩니다 (정수 인덱서가 있으면 쉽게 정렬 할 수 있지만 필수 사항은 아님).
phoog

2
편집과 관련하여 속성을 인터페이스 유형으로 제한하는 것은 메모리가 아니라 캡슐화에 관한 것입니다. 고려 : private IEnumerable<int> _integers = new List<int> { 1, 2, 3 };같은 메모리를 사용private List<int> _integers = new List<int> { 1, 2, 3 };
phoog

13
@TravisJ : 의 구현과 별개 로 변경 가능한 구조 유형을 반환하는 메소드 List<T>가 있습니다. 대부분의 컨텍스트에서 해당 유형은 독립형 힙 오브젝트보다 약간 더 나은 성능을 제공합니다. C # 및 vb.net과 같이 덕형 열거자를 사용하는 컴파일러는 코드를 생성 할 때이 기능을 활용할 수 있습니다 . 이 경우 에 캐스팅 전과 의 방법은 최적화가 불가능 렌더링, 힙 - 할당 된 개체를 반환합니다. GetEnumerator()IEnumerable<T>List<T>.EnumeratorforeachList<T>IEnumrable<T>foreachIEnumerable<T>.GetEnumerator()
supercat

85

ICollection<T>IEnumerable<T>인터페이스는 항목을 추가하거나 제거하거나 컬렉션을 수정하는 방법을 제공하지 않기 때문에 사용됩니다 .


3
List <T>와 비교하면 어떻습니까?
Jan Carlo Viray

12
List<T>구현 ICollection<T>합니다.
쓰셨

비 제네릭 ICollection은 항목을 추가하는 방법을 허용하지 않지만 일반적으로 모든 것을 열거하는 것보다 훨씬 빠른 멤버를 IEnumerable<T>제공 하기 때문에 유용한 보조 기능 Count입니다. 참고는 IF 것을 IList<Cat>이상이 ICollection<Cat>을 기대 코드에 전달 IEnumerable<Animal>Count()는 제네릭이 아닌를 구현하는 경우 확장 방법은 빠른 것입니다 ICollection,하지만 그것은 단지 일반 인터페이스를 구현하지 않을 경우 전형적인 때문에 ICollection<Cat>구현하지 않습니다 ICollection<Animal>.
supercat

58

에 대한 귀하의 질문에 답변 List<T>:

List<T>클래스입니다. 인터페이스를 지정하면 구현의 유연성이 향상됩니다. 더 좋은 질문은 "왜 안돼 IList<T>?"입니다.

이 질문에 답하려면 정수 인덱싱에 IList<T>추가 할 ICollection<T>항목 을 고려하십시오 . 즉, 항목에 임의의 순서가 있으며 해당 순서를 참조하여 검색 할 수 있습니다. 항목은 다른 상황에서 다르게 주문해야하기 때문에 이것은 대부분의 경우 의미가 없습니다.


21

ICollection과 IEnumerable 간에는 몇 가지 기본 차이점이 있습니다.

  • IEnumerable -Enumerator를 가져 오기 위해 GetEnumerator 메소드 만 포함하며 루핑을 허용합니다.
  • ICollection 에는 추가, 제거, 포함, 개수, CopyTo와 같은 추가 메서드가 포함됩니다.
  • ICollection 은 IEnumerable에서 상속됩니다.
  • ICollection을 사용하면 add / remove와 같은 메소드를 사용하여 콜렉션을 수정할 수 있습니다. IEnumerable과 같은 일을 할 자유가 없습니다.

간단한 프로그램 :

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

이런 식으로 기억합니다.

  1. IEnumerable에는 컬렉션의 값을 읽을 수는 있지만 쓸 수는없는 GetEnumerator () 메서드가 있습니다. 열거자를 사용하는 복잡성의 대부분은 C #의 각 문마다 처리됩니다. IEnumerable에는 Current 요소가 하나 있는데 현재 요소를 반환합니다.

  2. ICollection은 IEnumerable을 구현하고 가장 많이 사용되는 속성이 Count 인 몇 가지 추가 속성을 추가합니다. ICollection의 일반 버전은 Add () 및 Remove () 메서드를 구현합니다.

  3. IList는 IEnumerable과 ICollection을 모두 구현하고 항목에 정수 색인 액세스를 추가합니다 (주문이 데이터베이스에서 수행 될 때 일반적으로 필요하지 않음).


4
당신이 쓴 것을 기반으로 ICollection과 IList는 동일합니다. ICollection에 존재하지 않는 IList에 추가 된 것을 추가하십시오.
내기

IEnumerable 및 ICollection의 모든 기능과 추가 기능이 포함 된 System.Collection의 IList VS IList, IList 전용 인터페이스입니다. IList에는 Insert 및 Remove 메소드가 있습니다. 두 방법 모두 매개 변수에서 색인을 승인합니다. 따라서 콜렉션을 통한 인덱스 기반 조작을 지원합니다.
E.Meir

7

사용의 기본 아이디어는 ICollection유한 한 양의 데이터에 대한 읽기 전용 액세스를위한 인터페이스를 제공하는 것입니다. 실제로 ICollection.Count 속성이 있습니다. IEnumerable논리적 지점, 소비자가 암시 적으로 지정한 조건 또는 열거의 끝까지 읽는 일부 데이터 체인에 더 적합합니다.


14
ICollection읽기 전용 인 TIL ICollection<T>은 그렇지 않습니다.
Carl G

2

탐색 속성은 일반적으로 지연로드와 같은 특정 Entity Framework 기능을 활용할 수 있도록 가상으로 정의됩니다.

탐색 특성이 여러 엔티티 (다 대다 또는 일대 다 관계에서와 같이)를 보유 할 수있는 경우 해당 유형은 ICollection과 같이 항목을 추가, 삭제 및 업데이트 할 수있는 목록이어야합니다.

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- 응용


2

과거 에 한 일은 내 저장소 클래스 의 메소드에서 열거, 정렬 / 순서 또는 수정 을 수행 해야하는지 여부에 따라 IList<Class>, ICollection<Class>또는 IEnumerable<Class>(정적 목록 인 경우)을 사용하여 내부 클래스 콜렉션을 선언 하는 것입니다. . 객체를 열거하고 정렬해야 할 때 IEnumerable 메서드 내에서 컬렉션으로 작업 할 temp 를 만듭니다 . 이 연습은 컬렉션이 상대적으로 작은 경우에만 효과적이지만 일반적으로 좋은 방법 일 수 있습니다 idk. 이것이 왜 좋은 습관이 아닌지에 대한 증거가 있다면 저를 정정하십시오.List<Class>


0

논리와 함께 / 논리적으로 생각하고 질문에서이 세 가지 인터페이스를 명확하게 이해할 수 있습니다.

일부 인스턴스의 클래스가 System.Collection.IEnumerable 인터페이스를 구현할 때 간단히 말해서이 인스턴스는 열거 가능하고 반복 가능하다고 말할 수 있습니다. 즉,이 인스턴스는 단일 루프에서 어떤 식 으로든 go / get / pass /를 허용합니다. 이 인스턴스에 포함 된 모든 항목과 요소를 통과하거나 반복합니다.

즉,이 인스턴스에 포함 된 모든 항목과 요소를 열거 할 수도 있습니다.

System.Collection.IEnumerable 인터페이스를 구현하는 모든 클래스는 인수를 취하지 않고 System.Collections.IEnumerator 인스턴스를 반환하는 GetEnumerator 메서드도 구현합니다.

System.Collections.IEnumerator 인터페이스의 인스턴스는 C ++ 반복자와 매우 유사하게 작동합니다.

어떤 인스턴스의 클래스가 System.Collection.ICollection 인터페이스를 구현할 때, 간단히 말해서,이 인스턴스는 사물의 모음이라고 말할 수 있습니다.

이 인터페이스의 일반 버전, 즉 System.Collection.Generic.ICollection은이 정보가 컬렉션에있는 것들의 유형을 명시 적으로 나타 내기 때문에보다 유익합니다.

이론적으로 모든 컬렉션은 열거 가능하고 반복 가능하며 이론적으로 모든 항목과 요소를 처리 할 수 ​​있기 때문에 이것은 합리적이고 합리적이며 논리적이며 System.Collections.ICollection 인터페이스가 System.Collections.IEnumerable 인터페이스에서 상속한다는 것을 의미합니다. 모든 컬렉션에서.

System.Collections.ICollection 인터페이스는 변경 가능한 유한 동적 컬렉션을 나타냅니다. 즉, 존재하는 항목을 컬렉션에서 제거하고 동일한 항목에 새 항목을 추가 할 수 있습니다.

이것은 System.Collections.ICollection 인터페이스에 "Add"및 "Remove"메소드가있는 이유를 설명합니다.

System.Collections.ICollection 인터페이스의 인스턴스가 유한 컬렉션이므로 "finite"라는 단어는이 인터페이스의 모든 컬렉션에 항상 제한된 수의 항목과 요소가 있음을 의미합니다.

System.Collections.ICollection 인터페이스의 Count 속성은이 숫자를 반환한다고 가정합니다.

System.Collections.IEnumerable 인터페이스에는 System.Collections.ICollection 인터페이스에있는 이러한 메소드 및 특성이 없습니다. System.Collections.IEnumerable에 System.Collections.ICollection 인터페이스에있는 이러한 메소드 및 특성이 있다는 의미는 없습니다.

이 논리는 열거 가능하고 반복 가능한 모든 인스턴스가 반드시 컬렉션이 아니며 반드시 변경 가능한 것은 아니라고 말합니다.

변경 가능하다고 말하면 열거 가능하고 반복 가능한 무언가에서 무언가를 추가하거나 제거 할 수 있다고 즉시 생각하지는 않습니다.

예를 들어, 소수의 소수 시퀀스를 방금 만든 경우이 유한 소수 시퀀스는 실제로 System.Collections.IEnumerable 인터페이스의 인스턴스입니다. 이제 하나의 루프에서이 유한 시퀀스의 모든 소수를 처리 할 수 ​​있기 때문입니다. 콘솔 창이나 화면에 각각 인쇄하는 것과 같이 각 작업으로 수행하려는 작업을 수행하지만이 유한 소수 시퀀스는 System.Collections.ICollection 인터페이스의 인스턴스가 아닙니다. 유한 한 소수의 소수에 복합 수를 추가합니다.

또한 다음 반복에서 현재 반복의 현재 소수에 가장 가까운 다음 소수를 얻으려면이 유한 소수 시퀀스에서 존재하는 소수를 제거하고 싶지 않습니다.

또한 System.Collections.IEnumerable 인터페이스의 GetEnumerator 메소드에서 "수율 리턴"을 사용, 코딩 및 작성하여 소수를 생성하고 메모리 힙에 아무것도 할당하지 않은 다음 GC (가비지 콜렉터)를 모두 운영 체제 메모리를 낭비하고 성능을 저하 시키므로 힙에서이 메모리를 할당 해제하고 해제하십시오.

힙에서 동적 메모리 할당 및 할당 해제는 System.Collections.ICollection 인터페이스의 메소드 및 특성을 호출 할 때 수행해야하지만 System.Collections.IEnumerable 인터페이스의 메소드 및 특성을 호출 할 때는 수행하지 않아야합니다 (System.Collections.IEnumerable 인터페이스에는 1 가지 방법과 0 가지 속성).

이 스택 오버플로 웹 페이지에서 다른 사람들이 말한 것처럼 System.Collections.IList 인터페이스는 단순히 순서를 지정할 수있는 컬렉션을 나타내며 System.Collections.IList 인터페이스 의 메서드가 System.Collections.ICollection 인터페이스의 메서드와 달리 인덱스와 함께 작동하는 이유를 설명합니다.

간단히 말해 System.Collections.ICollection 인터페이스는 해당 인스턴스가 주문 가능하다는 것을 의미하지는 않지만 System.Collections.IList 인터페이스는이를 의미합니다.

이론적으로 정렬 된 세트는 정렬되지 않은 세트의 특수한 경우입니다.

이것은 또한 의미가 있고 System.Collections.IList 인터페이스가 System.Collections.ICollection 인터페이스를 상속하는 이유를 설명합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.