컬렉션 요청에 항목이 없을 때 예상되는 동작


13

다음과 같은 것들이 있다고 가정 해 봅시다.

List<Thing> theThings = fubar.Things.All();

반환 할 것이 없다면 fubar.Things.All ()이 무엇을 반환 할 것입니까?

편집 : 의견 주셔서 감사합니다. 조금 기다렸다가 가장 많은 항목을 수락합니다.

나는 지금까지의 답변, 특히 빈 컬렉션을 제안하는 답변에 동의합니다. 공급 업체는 위 예제와 유사한 여러 호출을 API에 제공했습니다. 작년에 API를 통해 460 만 달러의 매출을 올린 공급 업체 인 BTW. 그들은 근본적으로 동의하지 않는 것을합니다. 예외를 던집니다.


꽤 견고한 합의 인 것 같습니다 [여기] [1] : 빈 모음. 항상. [1] : stackoverflow.com/questions/1969993/…
Jesse C. Slicer

의 데이터 유형은 무엇입니까 Things? 그것이 가지고 의미가있는 경우 Things필드는 null를, 그것은 당신이 당신의 호출하기 전에 널 (null)을 확인하지 않았기 때문에 당신이 예외를 수신하는 의미가 있습니다 All(). 그러나 나는 fubar.Thingsnull 대신 빈 컬렉션을 반환해야 한다고 생각하는 사람들에 동의합니다 .
콜린 D

콜린, 당신이 뭘하는지 봅니다. 이 경우 상황이 존재하고 All ()이 정적이라고 가정 할 수 있습니다. 예외는 다른 이유가 아니라 컬렉션이 비었을 때만 적용됩니다.
abscode

세상에 그들은 예외를 던졌습니다 ...! o_O
스튜어트 마크

이제, 더 흥미로운 질문은 사람이 그런 일반적인 경우에 던져 할 수있는 지구에 무슨 이유가있을 것이다, 또는 케이스를 만드는 것 ?? 특별한 영장 던지기 너무!
Martin Ba

답변:


29

두 가지 가능성 중 (즉 null, 빈 컬렉션 반환 또는 빈 컬렉션 반환) 호출자가 반환 값 확인을 건너 뛸 수 있기 때문에 빈 컬렉션 반환을 선택합니다. 이것을 쓰는 대신

List<Thing> theThings = fubar.Things.All();
if (theThings != null) {
    for (Thing t : theThings) {
        t.doSomething();
    }
}

그들은 이것을 쓸 수있을 것입니다 :

List<Thing> theThings = fubar.Things.All();
for (Thing t : theThings) {
    t.doSomething();
}

이 두 번째 코드 조각은 중첩 수준이 1 씩 낮아지기 때문에 더 짧고 읽기 쉽습니다.


2
또한 '세트가 비어 있습니다'(항목이 없음)이므로 개념적으로 이해하기가 더 쉽다고 생각합니다. 널은 '설정이 없습니다'이며 이는 상당히 다릅니다. (이것은 논리적으로 불가능한 것들도 포함해야합니다-홀수가 아닌 빈 항목이어야하며 null이 아닌 모든 항목 세트). 솔직히 아니에요 있는지 무엇을 (논리적으로) 널 세트를 구성하는 것 (심지어 만약 당신이 섬에 알몸 벅, 당신의 재산은 공집합이 아닌 널 하나입니다)
시계 - 뮤즈

@ X-Zero 그러나 만약 당신이 알몸이라면, 배낭을 가지고 있지 않기 때문에 "배낭의 소지품"은 널 세트를 반환 할 수 있습니다. 그것은 BackpackNotFoundException 수 있지만, 정말 예기치 않은 경우에만 가능합니다. 예를 들어 섬 생존 게임에서는 정상적인 상태 여야합니다.
이즈 카타

여분의 null 확인은 밤에 잠을 잘 수 있도록 도와줍니다.
Joel B

6

나는 빈 목록을 기대할 것이다. theThings여전히 객체가 될 것이지만, theThings.Count또는 theThings.size()반환합니다 0.


5

이와 같은 설계 문제는 Null Object 패턴으로 해결됩니다.

... 존재하지 않는 고객과 같은 객체가 없음을 전달하기 위해 null 참조를 사용하는 대신 예상 인터페이스를 구현하지만 메소드 본문이 비어있는 객체를 사용합니다. 작동하는 기본 구현에 비해이 방법의 장점은 Null 개체가 매우 예측 가능하며 부작용이 없다는 것입니다.

예를 들어, 함수는 디렉토리에서 파일 목록을 검색하고 각각에 대한 조치를 수행 할 수 있습니다. 빈 디렉토리의 경우 한 가지 응답은 예외가 아니라 목록이 아닌 null 참조를 반환하는 것일 수 있습니다. 따라서 목록을 기대하는 코드는 실제로 계속하기 전에 목록이 있는지 확인해야하므로 디자인이 복잡해질 수 있습니다 ...

귀하의 경우에 특히 적용 할 수있는 제안 ( s List가없는 경우 반환 Thing)은 다음과 같습니다.

... 대신 null 객체 (즉 빈 목록 )를 반환하면 반환 값이 실제로 목록인지 확인할 필요가 없습니다. 호출 함수는 단순히 정상적으로 목록을 반복하여 효과적으로 아무것도하지 않을 수 있습니다. 그러나 반환 값이 null 개체 (예 : 빈 목록)인지 확인하고 원하는 경우 다르게 반응 할 수 있습니다.


3

IMHO는 EMPTY 값을 반환해야합니다. C #에 대해서는 잘 모르지만 Java에는 다음과 같은 것이 있습니다.

  List list = Collections.EMPTY_LIST;
  Set set = Collections.EMPTY_SET;
  Map map = Collections.EMPTY_MAP;

  // For the type-safe 
  List<String> s = Collections.emptyList();
  Set<Long> l = Collections.emptySet();
  Map<Date> d = Collections.emptyMap();

http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Collections.html


1
는 C # 동등한은 Enumerable.Empty<T>()빈을 반환, IEnumerable<T>(참조 msdn.microsoft.com/en-us/library/bb341042.aspx를 )
애브너 샤 하르 - Kashtan

1
현재 문서는 다음과 같습니다. docs.oracle.com/javase/7/docs/api/java/util/Collections.html-1.4.2 문서는 약 10 년이되었습니다.
스튜어트 마크

2

호출 코드에서 null 확인을 작성하지 않도록 할 수 있기 때문에 null 값을 반환하는 것에 대해 빈 컬렉션을 반환합니다.


2

두 가지 솔루션은 서로 다른 의미를 갖습니다.

반품 대상이 0 개이면 항상 빈 컬렉션을 반환합니다. 디렉토리 목록의 경우를 보자. 디렉토리에 파일이 없으면 빈 파일 모음을 반환합니다.

반면에 디렉토리가 존재하지 않으면 실제로 적절하지 않습니다. "나는 아무것도 반환 할 수 없습니다"는 완전히 다른 것을 의미합니다. 이 경우 상황에 따라 null을 반환하거나 예외를 throw해야합니다. 아무 문제가없는 것처럼 빈 컬렉션 만 반환하면 안됩니다.


매우 합리적인 설명. 반환 된 결과는 유효하지 않은 상태를 다루지 않아야합니다. 이에 대한 예외가 있습니다.
Ivaylo Slavov
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.