2009-03-05 5 views
4

최근에 다른 곳에서 *에 대한 내 견해를 밝혔지만 추가 분석이 필요하다고 생각하므로 자체 질문으로 게시하고 있습니다.IEnumerable과 같은 인터페이스 또는 List <>와 같은 구체적인 클래스를 사용해야합니까?

프로그램에서 컨테이너를 만들고 전달해야한다고 가정 해 보겠습니다. 적어도이 단계에서는 다른 종류의 컨테이너와 다른 컨테이너에 대해 강한 견해를 갖고 있지는 않지만 아마도 하나를 선택합니다. 논증의 목적으로 목록 <>을 사용한다고 가정 해 봅시다.

질문 : C#의 고수준 인터페이스를 수락하고 반환하는 방법을 쓰는 것이 더 좋습니까? IEnumerable? 또는 내가 선택한 특정 컨테이너 클래스를 가져와 전달하는 메서드를 작성해야합니다.

내가 결정할 요인과 기준은 무엇입니까? 어떤 종류의 프로그램이 하나 또는 다른 혜택을 누릴 수 있습니까? 컴퓨터 언어가 귀하의 결정에 영향을 줍니까? 공연? 프로그램 크기? 개인 스타일?

는 (심지어 중요합니까?)

** (숙제 :.. 그것을 찾을하지만 내 자신을 찾아 전에 그렇게하지 편견 당신으로, 여기에 답변을 게시하시기 바랍니다) *

답변

5

유일한에게 결정에 영향을 미치는 것은 매개 변수를 사용하는 방법입니다. 이 과정을 반복하는 경우 IEnumerable<T>을 사용하십시오. 색인 된 회원 (예 : var x = list[3])에 액세스하거나 목록을 수정하는 경우 (예 : list.Add(x)) ICollection<T> 또는 IList<T>을 사용하십시오.

16

메서드는 항상 함수를 실행하는 데 필요한 최소한의 특정 형식을 받아 들여야합니다. 메서드를 열거해야하는 경우 IEnumerable을 수락하십시오. 정의 된대로 IList<> 특정 작업을 수행해야하는 경우 IList<>을 제공해야합니다.

+0

동의하지만, 거의 똑같은 질문을하고 있습니다. 내 코드가 IEnumerable을 사용하는 것을 어색하게 느끼기 때문입니다. List 대신 foos = fooQuery.GetFoos()를 사용하면 List foos = new List (fooQuery.GetFoos())가됩니다. 내가 놓친 게 있니? 아니면 유연성을 위해 우리가 지불하는 가격입니까? – si618

+0

위의 설명을 사용하는 예는 결과를 확인하려는 단위 테스트에 있습니다. IList.Count, 실제 사용법은 IList가 실제로 필요하지 않으며 IEnumerable만으로도 충분하지만 그냥 어색하다고 느낀다. – si618

+0

@Si 나는 우리가 여기 다른 것들에 대해 이야기하고 있다고 생각한다. 이 질문은 메서드 내부의 영역에 관한 것입니다. 메소드 밖의 반환 유형 및 사용에 대해 설명합니다. –

0

중요하지만 정확한 해결책은 사용법에 따라 다릅니다. 간단한 열거 형을 수행하기 만하면 IEnumerable을 사용하여 구현자를 전달하여 필요한 기능에 액세스 할 수 있습니다. 그러나 목록 기능이 필요하고 우연히 메서드가 호출 될 때 목록의 새 인스턴스를 만들지 않으려는 경우 전달 된 열거 형은 목록이 아니며 목록과 함께 이동합니다.

3

항상 상충 관계가 있습니다. 엄지의 일반적 규칙은 가능한 한 계층 구조를 높게 선언하는 것입니다. 그래서 필요한 모든 것이 IEnumerable의 메소드에 액세스하면 필요한 것이 있습니다.

최근 질문의 또 다른 예는 파일 * (또는 파일 설명자) 대신 파일 이름을 사용하는 C API입니다. 파일명은 전달할 수있는 것들이 얼마나 제한되어 있습니다 (파일 설명자로 전달할 수있는 많은 것들이 있지만 파일 이름이있는 것만 있습니다).

일단 캐스팅을 시작하면 너무 높아 졌거나 더 구체적인 유형을 취하는 두 번째 방법을 만들어야합니다.

내가 생각할 수있는 유일한 예외는 속도가 절대적이어야하고 가상 메소드 호출의 비용을 처리하기를 원하지 않는다는 것입니다. 특정 유형을 선언하면 가상 함수의 오버 헤드가 제거됩니다 (언어/환경/구현에 따라 다르지만 일반적으로 올바른 문이 될 수 있음).

0

나는 비슷한 C# 질문 here에 대답했습니다.내 의견으로는 컬렉션의 경우 일반적으로 T의 숫자가 IEnumerable 인 가장 간단한 계약을 제공해야한다고 생각합니다.

구현은 내부 BCL 유형으로 제공 될 수 있습니다. Set, Collection, List 기타 - 귀하의 필수 구성원이 귀하의 유형에 의해 노출됩니다.

추상 유형은 항상 구체적인 유형으로 구현되는 간단한 BCL 유형을 상속 할 수 있습니다. 내 생각에 이것은 LSP을 쉽게 준수 할 수 있습니다.

3

유로 미첼리가 이미 내 대답을 알고 있기 때문에이 질문을 던져 준 토론이있었습니다. 그러나 여기에 있습니다! :)

저는 Linq가 이미이 질문에 대한 훌륭한 답을 제공한다고 생각합니다. 가능한 일련의 항목에 대해 가장 간단한 인터페이스를 사용하면 시퀀스를 구현하는 방법에 대해 최대한의 유연성을 제공하므로 게으른 생성을 허용하여 성능을 저하시키지 않으면 서 생산성을 향상시킵니다 (실제 의미가 아님).

조숙 한 추상화는 비용을 가질 수 있지만 사실은 새로운 추상화를 발견하거나 발명하는 비용입니다. 하지만 이미 완벽하게 제공되는 것들이 있다면, 그것들을 이용하지 않는 것이 좋을 것입니다. 이것이 제네릭 컬렉션 인터페이스가 여러분에게 제공하는 것입니다.

클래스에있는 모든 데이터를 공개하는 것이 "쉽다"라고 말하는 사람들이 있습니다. 액세스해야 할 경우를 대비하여. 같은 방식으로, 유로는 IList<T> (또는 심지어 콘크리트 클래스 List<T>)과 같은 컨테이너에 대한 풍부한 인터페이스를 사용하고 나중에 문제를 정리하는 것이 더 나을 것이라고 조언했습니다.

하지만 액세스하지 않으려는 클래스의 데이터 멤버를 숨기고 나중에 쉽게 해당 클래스의 구현을 수정할 수 있도록하는 것이 가장 간단한 인터페이스를 사용해야한다고 생각합니다. 일련의 항목을 참조 할 수 있습니다. 실용적으로 단순하고 기본적인 것을 드러내는 것으로 시작한 다음, 나중에 느슨하게하고 느슨하게하는 것부터 시작하여 느슨하게하고 질서 정연하게하는 것보다 쉽습니다.

따라서 IEnumerable<T>이 시퀀스를 나타내는 것으로 가정합니다. 그런 다음 Add 또는 Remove 개의 항목이 필요하지만 색인 색인 조회가 여전히 필요하지 않은 경우 IEnumerable<T>을 상속하는 IContainer<T>을 사용하면 다른 코드와 완벽하게 상호 운용 될 수 있습니다.

이렇게하면 코드가 데이터로 수행 할 수있는 작업이 무엇인지 정확히 알 수 있습니다.

작은 프로그램은 더 적은 추상화를 요구합니다. 그러나 성공하면 큰 프로그램이되는 경향이 있습니다. 처음에 간단한 추상화를 사용하면 훨씬 쉽습니다.

관련 문제