문제

사용하는데 문제가 있는지요 IEnumerable<T> 반환 유형으로?FxCop이 반품에 대해 불평합니다. List<T> (돌아가라고 조언함 Collection<T> 대신에).

글쎄요, 저는 항상 "가능한 최소한의 것을 받아들이고 최대한의 것을 돌려주세요"라는 규칙을 따라왔습니다.

이런 관점에서 돌아가면 IEnumerable<T> 나쁜 일이지만 "지연 검색"을 사용하려면 어떻게 해야 합니까?또한, yield 키워드는 정말 좋은 것입니다.

도움이 되었습니까?

해결책

이것은 실제로 두 부분 질문입니다.

1) 본질적으로 ienumerable을 반환하는 데 문제가 있습니까?u003CT>

전혀 아무것도 없습니다. 실제로 C# ITERATORS를 사용하는 경우 예상되는 동작입니다. 목록으로 변환합니다u003CT> 또는 다른 컬렉션 클래스는 선제 적으로 좋은 생각이 아닙니다. 그렇게하는 것은 발신자가 사용 패턴을 가정하는 것입니다. 발신자에 대해 아무것도 가정하는 것이 좋은 생각이 아닙니다. 그들은 ienumerable을 원하는 좋은 이유가있을 수 있습니다.u003CT> . 아마도 그들은 그것을 완전히 다른 컬렉션 계층으로 변환하고 싶어 할 것입니다 (이 경우 목록으로의 변환이 낭비됩니다).

2) ienumerable 이외의 것을 반환하는 것이 바람직한 상황이 있습니까?u003CT> ?

예. 발신자에 대해 많이 가정하는 것은 좋은 생각은 아니지만 자신의 행동에 따라 결정을 내리는 것은 완벽하게 괜찮습니다. 지속적으로 업데이트되고있는 객체로 요청을 대기하는 멀티 스레드 객체가있는 시나리오를 상상해보십시오. 이 경우 원시 ienumerable을 반환합니다u003CT> 무책임합니다. 컬렉션이 수정 되 자마자 열거 가능한 것은 무효화되어 execption이 발생합니다. 대신 구조의 스냅 샷을 가져 와서 그 값을 반환 할 수 있습니다. 목록에서 말하십시오u003CT> 형태. 이 경우 나는 객체를 직접 구조 (또는 인터페이스)로 반환합니다.

이것은 확실히 드문 경우입니다.

다른 팁

아니, IEnumerable<T> a 좋은 당신이 유망한 것은 "(유형) 값의 시퀀스"이기 때문에 여기서 돌아올 것입니다. LINQ 등에 이상적이며 완벽하게 사용할 수 있습니다.

발신자는이 데이터를 목록 (또는 무엇이든)에 쉽게 넣을 수 있습니다.ToList, ToArray, 등).

이 접근법을 사용하면 모든 데이터를 버퍼링하지 않고 뒤로 뒤로 값을 뿌릴 수 있습니다. 확실히 goodie. 나는 썼다 또 다른 유용한 IEnumerable<T> 장난 다른 날도.

당신의 원칙에 대해 : "당신이 할 수있는 최소한을 받아들이지 만 최대 값을 반환하십시오".

큰 프로그램의 복잡성을 관리하는 열쇠는 정보 숨기기. 당신의 방법이 빌드하여 작동하는 경우 List<T>, 그 유형을 반환 하여이 사실을 밝힐 필요는 없습니다. 그렇다면 발신자가 돌아 오는 목록을 수정할 수 있습니다. 이것은 캐싱 또는 게으른 반복을 수행하는 능력을 제거합니다. yield return.

따라서 더 나은 원칙은 다음과 같은 기능을 따르는 것입니다. "작업 방식에 대해 가능한 한 적은 공개"입니다.

ienumerable은 나에게 괜찮지 만 약간의 단점이 있습니다. 클라이언트는 결과를 얻기 위해 열거해야합니다. 카운트 등을 확인하는 방법이 없습니다. 목록은 너무 많은 제어를 노출시키기 때문에 나쁘다. 클라이언트는 등을 추가/제거 할 수 있으며 그로 인해 나쁜 일이 될 수 있습니다. 컬렉션은 적어도 FXCOP의 견해에서 가장 큰 타협으로 보입니다. 나는 내 상황에서 적절한 것으로 보이는 것을 모두 사용합니다 (예 : 읽기 전용 컬렉션을 반환하려면 수집을 반환 유형 및 반환 목록으로 노출시킵니다. asreadonly () 또는 Ienumerable을 수율 등을 통해 게으른 평가할 수 있습니다). 사례별로 가져 가십시오

"가능한 한 최소한을 받아들이고 최대한의 것을 돌려라"는 것이 제가 옹호하는 것입니다.메소드가 객체를 반환할 때 실제 유형을 반환하지 않고 기본 유형을 반환하여 객체의 기능을 제한해야 하는 이유는 무엇입니까?그러나 이는 인터페이스를 디자인할 때 "최대"(실제 유형)가 무엇인지 어떻게 알 수 있는지에 대한 의문을 제기합니다.대답은 매우 간단합니다.인터페이스 디자이너가 애플리케이션/구성 요소 외부에서 구현될 개방형 인터페이스를 설계하는 극단적인 경우에만 실제 반환 유형이 무엇인지 알 수 없습니다.현명한 디자이너는 메소드가 수행해야 하는 작업과 최적/일반 반환 유형이 무엇인지 항상 고려해야 합니다.

예:객체의 벡터를 검색하는 인터페이스를 설계 중이고 반환된 객체의 수가 가변적이라는 것을 알고 있다면 똑똑한 개발자는 항상 List를 사용할 것이라고 가정합니다.누군가 배열을 반환할 계획이라면 자신이 소유하지 않은 다른 레이어에서 데이터를 반환하는 것이 아니라면 그 사람의 능력에 대해 의문을 제기할 것입니다.그리고 이것이 아마도 FxCop이 ICollection(목록 및 배열의 ​​공통 기반)을 옹호하는 이유일 것입니다.

위에서 언급했듯이 고려해야 할 몇 가지 다른 사항이 있습니다.

  • 반환된 데이터가 변경 가능하거나 불변이어야 하는지 여부

  • 반환된 데이터가 여러 호출자 간에 공유되는 경우

LINQ 게으른 평가와 관련하여 95% 이상의 C# 사용자가 무결성을 이해하지 못한다고 확신합니다.너무 엉뚱해요.OO는 메서드 호출 시 구체적인 상태 변경을 촉진합니다.LINQ 지연 평가는 식 평가 패턴에서 런타임 상태 변경을 촉진합니다(고급 사용자가 아닌 경우 항상 따르는 것이 아님).

반환 ienumerableu003CT> 당신이 진정으로 열거를 반환하는 경우 괜찮습니다.

그러나 다른 사람들이 지적한 바와 같이, 발신자가 다른 정보 (예 : 카운트)가 필요한 경우 열거해야 할 단점이 있습니다. .NET 3.5 확장 방법 ienumerableu003CT> .Count는 반환 값이 ICollection을 구현하지 않으면 무대 뒤에서 열거됩니다.u003CT> 바람직하지 않을 수 있습니다.

나는 종종 일리스트를 돌려줍니다u003CT> 또는 icollectionu003CT> 결과가 컬렉션 인 경우 - 내부적으로 메소드가 목록을 사용할 수 있습니다.u003CT> 그리고 반환 또는 리턴 목록을 반환합니다u003CT> .ASREADOLY 수정으로부터 보호하려는 경우 (예 : 내부적으로 목록을 캐싱하는 경우). Afaik FXCOP는이 중 하나에 매우 만족합니다.

중요한 측면 중 하나는 a를 반환 할 때입니다 List<T> 당신은 실제 반환입니다 참조. 따라서 발신자가 목록을 조작 할 수 있습니다. 이것은 일반적인 문제입니다. 예를 들어, 비즈니스 계층을 반환합니다. List<T> GUI 층으로.

당신이 ienumerable을 반환한다고해서 목록을 반환 할 수 없다는 것을 의미하지는 않습니다. 아이디어는 불필요한 커플 링을 줄이는 것입니다. 발신자가 관심을 가져야 할 모든 것은 해당 목록을 포함하는 데 사용되는 정확한 유형의 컬렉션이 아니라 사물 목록을 얻는 것입니다. 배열로 뒷받침되는 것이 있다면, Count와 같은 것을 얻는 것은 어쨌든 빠질 것입니다.

나는 자신의지도가 훌륭하다고 생각합니다. 성능에 맞지 않고 반환하는 것에 대해 더 구체적으로 할 수 있다면 (예 : 결과에서 목록을 작성할 필요가 없습니다) 그렇게하십시오. 그러나 기능이 합법적으로 어떤 유형을 찾지 못하면 어떤 상황에서는 목록으로 작업하고 배열이있는 등의 일부에서는 Ienumerable을 반환하는 것과 같이 어떤 유형을 찾을 것인지 알 수 있습니다. . 당신이 돌아가고 싶은 모든 것의 "가장 큰 공통된 배수"라고 생각하십시오.

선택한 대답을 받아 들일 수 없습니다. 설명 된 시나리오를 다루는 방법이 있지만 목록을 사용하거나 사용하는 다른 것을 사용하는 것은 그 중 하나가 아닙니다. ienumerable이 반환되는 순간, 발신자가 foreach를 할 수 있다고 가정해야합니다. 이 경우 콘크리트 유형이 목록인지 스파게티인지는 중요하지 않습니다. 실제로 인덱싱은 특히 항목을 제거하는 경우 문제입니다.

반환 된 값은 스냅 샷입니다. 그것은 ienumerable의 현재 내용 일 수 있으며,이 경우 캐시 된 경우 캐시 된 사본의 클론이어야합니다. 더 역동적 인 경우 (SQL 쿼리의 고지대와 같은) 수율 수익률을 사용하십시오. 그러나 컨테이너가 마음대로 돌연변이되도록하고 Count 및 Indexer와 같은 방법을 공급하는 것은 멀티 스레드 세계에서 재난을위한 레시피입니다. 발신자가 코드를 제어 해야하는 컨테이너에서 추가 또는 삭제를 호출 할 수있는 능력조차 얻지 못했습니다.

또한 콘크리트 유형을 반환하면 구현에 잠겨 있습니다. 오늘날 내부적으로 목록을 사용하고있을 수 있습니다. 내일은 멀티 스레드가되어 스레드 안전 컨테이너 나 배열 또는 큐 또는 사전의 값 모음 또는 LINQ 쿼리 출력을 사용하고 싶을 것입니다. 콘크리트 반환 유형에 자신을 잠그면 코드를 변경하거나 반환하기 전에 변환을 수행해야합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top