List (of T)와 Collection (of T)의 차이점은 무엇입니까?


92

나는 그것들이 같은 방식으로 많이 사용되는 것을 보았고, 내가 이것을 더 잘 이해하지 못하면 돌이킬 수없는 디자인의 길을 갈 까봐 걱정된다. 또한 .NET을 사용하고 있습니다.

답변:


50

Collection<T>주위에 사용자 정의 가능한 래퍼 IList<T>입니다. 동안 IList<T>밀폐되지 않은, 어떤 사용자 정의 포인트를 제공하지 않습니다. Collection<T>의 메서드는 기본적으로 표준 IList<T>메서드에 위임 되지만 원하는 작업을 수행하도록 쉽게 재정의 할 수 있습니다. Collection<T>IList로 할 수 있다고 생각하지 않는 이벤트를 내부에 연결하는 것도 가능합니다 .

요컨대, 사실 이후에 확장하는 것이 훨씬 쉬우므로 잠재적으로 리팩토링이 훨씬 줄어들 수 있습니다.


@Marc Gravell, @Adam Lassek : 공용 void new InsertItem (...)으로 InsertItem (...) 메서드를 숨긴 다음 base.InsertItem (..)을 호출하여 List로 동일한 작업을 수행 할 수 없습니다. .) 안으로부터 ? 여전히 계약을 깨지 않을 것입니다. (이름은 목록에 '삽입'이지만 그럼에도 불구하고). 그렇다면 Collections <T>를 고수하는 데 큰 문제는 무엇입니까?
DeeStackOverflow

4
@DeeStackOverflow -에 보이는 것을, 즉 아무것도 - 메서드 숨기기가 다른 API를 사용하는 코드에서 사용되지 않기 때문에 IList, IList<T>, List<T>등 한마디로 말하면, 당신이 그것을 호출할지 여부를 모른다. 다형성이이를 수정합니다.
Marc Gravell

@AdamLassek : ObservableCollection<T>변경 사항에 대해 알리기 위해 메서드가 재정의되는 예제로 답변에 추가 할 수 있습니다 .
Kiran Challa 2015

84

C #에는 개체 모음을 나타내는 세 가지 개념이 있습니다. 기능 증가 순서는 다음과 같습니다.

  • 열거 가능 -정렬되지 않고 수정할 수 없음
  • 컬렉션 -항목 추가 / 제거 가능
  • 목록 -항목이 순서를 가질 수 있도록 허용합니다 (인덱스로 액세스 및 제거).

Enumerable 에는 순서가 없습니다. 세트에서 항목을 추가하거나 제거 할 수 없습니다. 세트의 항목 수를 얻을 수도 없습니다. 세트의 각 항목에 차례로 액세스 할 수 있습니다.

수집 은 수정 가능한 집합입니다. 세트에서 객체를 추가 및 제거 할 수 있으며 세트의 항목 수를 가져올 수도 있습니다. 그러나 여전히 순서가없고 순서가 없기 때문에 인덱스로 항목에 액세스 할 수없고 정렬 할 방법도 없습니다.

목록 은 정렬 된 개체 집합입니다. 목록을 정렬하고, 인덱스로 항목에 액세스하고, 인덱스로 항목을 제거 할 수 있습니다.

실제로 이러한 인터페이스를 살펴보면 서로를 기반으로 구축됩니다.

  • interface IEnumerable<T>

    • GetEnumeration<T>
  • interface ICollection<T> : IEnumerable<T>

    • Add
    • Remove
    • Clear
    • Count
  • interface IList<T> = ICollection<T>

    • Insert
    • IndexOf
    • RemoveAt

변수 또는 메소드 매개 변수를 선언 할 때 다음을 사용하도록 선택해야합니다.

  • IEnumerable
  • ICollection
  • IList

개념적으로는 개체 집합을 처리해야합니다.

목록의 모든 개체에 대해 무언가를 수행 할 수 있어야한다면 다음 만 필요합니다 IEnumerable.

void SaveEveryUser(IEnumerable<User> users)
{
    for User u in users
      ...
}

[사용자가에 보관하는 경우 상관 없어 List<T>, Collection<T>, Array<T>다른 사람 또는 아무것도. 당신은IEnumerable<T>인터페이스 .

세트에서 항목을 추가, 제거 또는 계산할 수 있어야하는 경우 컬렉션 을 사용하십시오 .

ICollection<User> users = new Collection<User>();
users.Add(new User());

정렬 순서에 관심이 있고 올바른 순서가 필요한 경우 List 를 사용하십시오 .

IList<User> users = FetchUsers(db);

차트 형식 :

| Feature                | IEnumerable<T> | ICollection<T> | IList<T> |
|------------------------|----------------|----------------|----------|
| Enumerating items      | X              | X              | X        |
|                        |                |                |          |
| Adding items           |                | X              | X        |
| Removing items         |                | X              | X        |
| Count of items         |                | X              | X        |
|                        |                |                |          |
| Accessing by index     |                |                | X        |
| Removing by indexx     |                |                | X        |
| Getting index of item  |                |                | X        |

List<T>Collection<T>에서 System.Collections.Generic이 인터페이스를 구현하는 두 개의 클래스가 있습니다; 그러나 그들은 유일한 수업이 아닙니다.

  • ConcurrentBag<T>주문한 개체 가방입니다 ( IEnumerable<T>).
  • LinkedList<T>색인 ( ICollection)으로 항목에 액세스 할 수없는 가방입니다 . 하지만 컬렉션에서 항목을 임의로 추가 및 제거 할 수 있습니다.
  • SynchronizedCollection<T> 인덱스별로 항목을 추가 / 제거 할 수있는 정렬 된 컬렉션

따라서 다음을 쉽게 변경할 수 있습니다.

IEnumerable<User> users = new SynchronizedCollection<User>();

SaveEveryUser(users);

tl; dr

  • 열거 가능 -정렬되지 않고 수정할 수없는 액세스 항목
  • 컬렉션 -수정 가능 (추가, 삭제, 개수)
  • 목록 -색인으로 액세스 가능

선택 개념 당신이 필요를, 다음 일치하는 클래스를 사용합니다.


11
OP는 구체적인 유형에 대해 물었고 인터페이스를 비교했습니다. 구체적인 유형 Collection <T>는 IList <T>를 구현하고 인덱스 기능으로 액세스합니다.
JJS 2015 년

2
대답은 좋지만 질문에서 벗어났습니다 .Collection <T> 및 List <T> 클래스에 대한 답변에 맞지 않습니다. 당신의 요점을 검증하려고하면 그들이 정당화하지 못하는 것을 의미합니다. 일반적인 대답의 경우 컬렉션이 정렬되지 않아 색인이 생성되지 않지만 목록이 정렬되어 특정 색인에 삽입이 가능하다는 것이 옳을 수 있습니다.
Kylo 르네

ICollection <T>의 기능을 사용하고 문제를 해결하고 가능성을 찾으려면 어떻게해야합니까?

2
목록이 정렬되어 있고 컬렉션이 순서가없는 경우 새로운 학습자 (예 : 나)가 선택하도록 쉽게 안내하는 큰 기능적 차이가 될 것입니다. 하지만 잠깐, 왜 컬렉션에 순서가 없다고 말합니까? 그것은 제공 같이 IndexOf ()RemoveAt을 () 는,이 정렬되도록, 방법되지? 내가 여기서 뭔가를 놓쳤나요?
RayLuo

1
@RayLuo 나는 구체적으로 ICollection<T>IList<T>. 다른 구체적인 구현은 다르게 동작 할 수 있습니다. 예를 들어 인터페이스를 List<T>통해에 액세스하는 경우 IEnumerable<T>목록에서 항목을 추가, 제거, 정렬 또는 계산할 방법이 없습니다.
Ian Boyd

43

List<T>응용 프로그램 코드 내에서 내부적으로 사용하기위한 것입니다. 수락하거나 반환하는 공개 API를 작성하지 않아야합니다.List<T> (대신 수퍼 클래스 또는 컬렉션 인터페이스 사용을 고려하십시오).

Collection<T> 사용자 지정 컬렉션에 대한 기본 클래스를 제공합니다 (직접 사용할 수 있음).

Collection<T>특정 기능이없는 경우 코드에서 사용 을 고려하십시오.List<T>필요한 .

위는 단지 권장 사항입니다.

[출처 : 프레임 워크 디자인 지침, 제 2 판]


자신의 상태 를 캡슐화하기 위해 모든 종류의 변경 가능한 객체를 사용 하는 유형은 해당 객체가 변경 될 때 소유자에게 알리는 수단이 없거나 해당 객체를 반환하는 메서드의 이름이없는 한 이러한 유형의 객체를 반환하지 않아야한다는 점에 유의할 가치가 있습니다. 객체는 새 인스턴스를 반환하고 있음을 분명히 의미합니다. 예를 들어 a Dictionary<string, List<string>>를 반환하는 List<string>것은 괜찮습니다. 딕셔너리의 상태 는 그 내용이 아니라 그 안에있는 목록 의 신원 만을 캡슐화 하기 때문입니다.
supercat

37

List<T>매우 다재다능하기 때문에 매우 일반적으로 사용되는 컨테이너입니다 ( Sort,Find 하지만 당신은 행동의 오버라이드 (override) 할 경우 (삽입에 대한 검사 항목을 예를 들어) 더 확장 지점이 없습니다 -, 등).

Collection<T>IList<T>(기본값은 List<T>) 주위의 래퍼입니다 . 확장 점 ( virtual메소드)이 있지만 Find. 간접적이므로.보다 약간 느리지 List<T>만 그다지 많지는 않습니다.

LINQ와에 여분의 방법 List<T>부터 덜 중요 해지고, 어쨌든을 제공하는 경향이있다 -에 - 객체 LINQ ... 예를 들어 First(pred), OrderBy(...)


6
Collection <T>에는 Linq-to-Objects에서도 foreach 메서드가 없습니다.
tuinstoel

7
@tuinstoel-그러나 추가하는 것은 간단합니다.
Marc Gravell

12

목록이 더 빠릅니다.

예를 들어

private void button1_Click(object sender, EventArgs e)
{
  Collection<long> c = new Collection<long>();
  Stopwatch s = new Stopwatch();
  s.Start();
  for (long i = 0; i <= 10000000; i++)
  {
    c.Add(i);
  }
  s.Stop();
  MessageBox.Show("collect " + s.ElapsedMilliseconds.ToString());

  List<long> l = new List<long>();
  Stopwatch s2 = new Stopwatch();
  s2.Start();
  for (long i = 0; i <= 10000000; i++)
  {
    l.Add(i);
  }
  s2.Stop();
  MessageBox.Show("lis " + s2.ElapsedMilliseconds.ToString());


}

내 컴퓨터 List<>에서 거의 두 배 빠릅니다.

편집하다

사람들이 왜 이것을 반대하는지 이해할 수 없습니다. 직장 컴퓨터와 가정용 컴퓨터 모두 List <> 코드가 80 % 더 빠릅니다.


1
어떻게 더 빠릅니까? 조회? 삽입? 제거? 검색? 왜 더 빠릅니까?
Doug T.

17
목록은 Collection보다 입력 할 글자 수가 적습니다. :)
RedFilter

1
컬렉션에는 더 적은 메서드가 있습니다. 따라서 더 빠릅니다. QED. (농담, 나는 트롤링하지 않습니다)
Ray

2
내 컴퓨터에서 시도해 보았고 목록이 약 20 % 더 빠릅니다. 이것이 왜 그런지에 대한 토론에 관심이 있습니다. 메모리를 할당하면 목록이 더 나을 수도 있습니다.
Ray

10
List의 메서드는 상속 할 수 없으므로 상속되었는지 확인하는 검사가 없습니다. 컬렉션의 메서드는 상속 가능합니다. 장점은 Collection을 기본 클래스로 사용하여 사용자 지정 컬렉션을 상속하고 만들 수 있다는 것입니다.
Richard Gadsden

11

목록은 항목의 순서가 중요한 컬렉션을 나타냅니다. 또한 정렬 및 검색 방법을 지원합니다. 컬렉션은 데이터에 대한 가정을 줄이고 데이터를 조작하는 방법을 더 적게 지원하는보다 일반적인 데이터 구조입니다. 사용자 지정 데이터 구조를 노출하려면 컬렉션을 확장해야합니다. 데이터 구조를 노출하지 않고 데이터를 조작해야하는 경우 목록이 더 편리한 방법 일 것입니다.


4

이것은 대학원 질문 중 하나입니다. 컬렉션 T는 일종의 추상입니다. 기본 구현이있을 수 있지만 (나는 .net / c # 사람이 아닙니다) 컬렉션에는 추가, 제거, 반복 등과 같은 기본 작업이 있습니다.

T 목록은 이러한 작업에 대한 몇 가지 세부 사항을 암시합니다. add는 일정한 시간이 걸리고 remove는 요소 수에 비례하는 시간이 걸리고 getfirst는 일정한 시간이 필요합니다. 일반적으로 목록은 일종의 컬렉션이지만 컬렉션이 반드시 일종의 목록은 아닙니다.


4

HanselmanCollection<T> 은 다음과 같이 말합니다. " 목록처럼 보이며 List<T>내부적으로도 있습니다. 모든 단일 메서드는 내부에 위임합니다 List<T>. 여기에는 List<T>.

편집 : Collection<T>System.Generic.Collections .NET 3.5에 존재하지 않습니다. .NET 2.0에서 3.5로 마이그레이션하는 경우 Collection<T>명백한 것이 누락되지 않는 한 많은 개체를 사용하는 경우 일부 코드를 변경해야합니다 .

편집 2 : Collection<T>이제 .NET 3.5의 System.Collections.ObjectModel 네임 스페이스에 있습니다. 도움말 파일은 다음과 같이 말합니다.

"System.Collections.ObjectModel 네임 스페이스에는 재사용 가능한 라이브러리의 개체 모델에서 컬렉션으로 사용할 수있는 클래스가 포함되어 있습니다. 속성 또는 메서드가 컬렉션을 반환 할 때 이러한 클래스를 사용하십시오."


4

이러한 모든 인터페이스는에서 상속하므로 IEnumerable이해해야합니다. 이 인터페이스를 사용하면 기본적으로 foreach 문 (C #)에서 클래스를 사용할 수 있습니다.

  • ICollection나열한 인터페이스 중 가장 기본적인 인터페이스입니다. 를 지원하는 열거 가능한 인터페이스 Count이며 그게 전부입니다.
  • IList모든 ICollection것이지만 항목 추가 및 제거, 인덱스로 항목 검색 등도 지원합니다. "객체 목록"에 가장 일반적으로 사용되는 인터페이스입니다.
  • IQueryableLINQ를 지원하는 열거 가능한 인터페이스입니다. 항상 IQueryableIList에서을 만들고 LINQ to Objects를 사용할 수 있지만 IQueryableLINQ to SQL 및 LINQ to Entities에서 SQL 문의 지연된 실행 에도 사용됩니다.
  • IDictionary고유 한 키를 값에 매핑한다는 점에서 다른 동물입니다. 또한 키 / 값 쌍을 열거 할 수 있다는 점에서 열거 할 수 있지만 그렇지 않으면 나열한 다른 목적과 다른 용도로 사용됩니다.

ICollection은 추가 / 제거 / 지우기를 지원합니다. msdn.microsoft.com/en-us/library/…
amnesia

4

MSDN에 따르면 List (Of T) .Add는 "an O (n) operation"( "Capacity"가 초과 된 경우)이고 Collection (Of T) .Add는 항상 "an O (1) operation"입니다. List가 Array 및 Collection a Linked List를 사용하여 구현되면 이해할 수 있습니다. 그러나 그 경우라면 Collection (Of T) .Item이 "an O (n) operation"이 될 것으로 예상합니다. 하지만- 아니야 !?! Collection (Of T) .Item은 List (Of T) .Item과 마찬가지로 "O (1) 작업"입니다.

그 위에 "tuinstoel"의 "Dec 29 '08 at 22:31"게시물은 위의 클레임 속도 테스트에서 List (Of T)를 보여줍니다 .Add to be faster than Collection (Of T) .Add that I'veproduced with Long과 String. MSDN에 따르면 그의 주장 80 %에 비해 33 % 더 빨라졌지만 "n"번은 그 반대 였어야합니다!?!


3

둘 다 동일한 인터페이스를 구현하므로 동일한 방식으로 작동합니다. 내부적으로 다르게 구현 될 수 있지만 테스트를 거쳐야합니다.

내가 보는 유일한 차이점은 네임 스페이스와 Collection<T>으로 표시된 사실 ComVisibleAttribute(false)이므로 COM 코드에서 사용할 수 없습니다.


그들은 다른 인터페이스를 구현합니다-List <T>는 IList <T>를 구현하지만 Collection <T>는 그렇지 않습니다.
Bevan

C #에서 그것을 시도 @Bevan, 그들은 두 인터페이스의 동일한 집합을 구현
Kylo 르네

1
즉 흥미로운 변화 @KyloRen입니다 - 그들은 않는다 지금 모두 동일한 인터페이스를 구현; 2008 년에는 그렇지 않았습니다.
Bevan에

1
@Bevan 흥미로운. 두 개의 다른 클래스의 이유가 무엇인지 확실하지 않습니다.
Kylo Ren 2016

3

다른 asnwers 외에도 일반 목록 및 수집 기능에 대한 간략한 개요를 편집했습니다. 컬렉션은 목록의 제한된 하위 집합입니다.

* =  현재
o = 부분적으로 존재

속성 / 메소드 컬렉션 < T > 목록 < T > --------------------------------------- -------      

Add()                *              *
AddRange()                          *
AsReadOnly()                        *
BinarySearch()                      *
Capacity                            *
Clear()              *              *
Contains()           *              *
ConvertAll()                        *
CopyTo()             o              *
Count                *              *
Equals()             *              *
Exists()                            *
Find()                              *
FindAll()                           *
FindIndex()                         *
FindLast()                          *
FindLastIndex()                     *
ForEach()                           *
GetEnumerator()      *              *
GetHashCode()        *              *
GetRange()                          *
GetType()            *              *
IndexOf()            o              *
Insert()             *              *
InsertRange()                       *
Item()               *              *
LastIndexOf()                       *
New()                o              *
ReferenceEquals()    *              *
Remove()             *              *
RemoveAll()                         *
RemoveAt()           *              *
RemoveRange()                       *
Reverse()                           *
Sort()                              *
ToArray()                           *
ToString()           *              *
TrimExcess()                        *
TrueForAll()                        *
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.