그것은 일반적인 질문입니다 (그러나 C #을 사용하고 있습니다), 가장 좋은 방법 (모범 사례)은 컬렉션을 반환 유형으로 갖는 메소드에 대해 null 또는 빈 컬렉션을 반환합니까?
답변
빈 컬렉션. 항상.
이것은 짜증나 :
if(myInstance.CollectionProperty != null)
{
foreach(var item in myInstance.CollectionProperty)
/* arrgh */
}
null
컬렉션을 반환하거나 열거 할 때 절대 반환 하지 않는 것이 가장 좋습니다 . 빈 열거 형 / 컬렉션을 항상 반환합니다. 그것은 앞서 말한 넌센스를 방지하고 동료와 클래스의 사용자가 자동차에 알을 낳는 것을 방지합니다.
속성에 대해 이야기 할 때는 항상 속성을 한 번 설정하고 잊어 버리십시오.
public List<Foo> Foos {public get; private set;}
public Bar() { Foos = new List<Foo>(); }
.NET 4.6.1에서는이를 상당히 많이 압축 할 수 있습니다.
public List<Foo> Foos { get; } = new List<Foo>();
열거 형을 반환하는 메서드에 대해 이야기 할 때 빈 열거 형을 쉽게 반환 할 수 있습니다 null
…
public IEnumerable<Foo> GetMyFoos()
{
return InnerGetFoos() ?? Enumerable.Empty<Foo>();
}
Enumerable.Empty<T>()
예를 들어, 새로운 빈 컬렉션이나 배열을 반환하는 것보다 사용하는 것이 더 효율적인 것으로 볼 수 있습니다.
답변
로부터 프레임 워크 디자인 가이드 라인 제 2 판 (페이지 256.) :
컬렉션 속성이나 컬렉션을 반환하는 메서드에서 null 값을 반환하지 마십시오. 빈 컬렉션이나 빈 배열을 대신 반환하십시오.
null을 반환하지 않는 이점에 대한 또 다른 흥미로운 기사가 있습니다 (Brad Abram의 블로그에서 무언가를 찾으려고 노력했으며 기사에 링크되었습니다).
편집 – 에릭 Lippert의 등은 이제 원래의 질문에 댓글을 달았습니다, 나는 또한 싶습니다 그의 뛰어난 기사 링크 .
답변
계약 및 구체적인 사례 에 따라 다릅니다 . 일반적으로 빈 컬렉션을 반환하는 것이 가장 좋지만 간혹 ( 드물게 ) :
null
좀 더 구체적인 것을 의미 할 수도 있습니다.- 귀하의 API (계약)가 강제로를 반환 할 수 있습니다
null
.
구체적인 예 :
- 컨트롤에서 라이브러리의 UI 구성 요소로, 빈 컬렉션이 전달되면 빈 테이블을 렌더링하거나 null이 전달되면 테이블이 전혀 렌더링되지 않을 수 있습니다.
- Object-to-XML (JSON / 무엇이든)
null
에서 요소가 누락되었다는 것을 의미하는 반면, 빈 컬렉션은 중복 (및 가능하지 않은)을 렌더링합니다<collection />
- null을 반환 / 전달해야한다고 명시 적으로 명시하는 API를 사용하거나 구현하고 있습니다.
답변
아직 언급되지 않은 또 다른 요점이 있습니다. 다음 코드를 고려하십시오.
public static IEnumerable<string> GetFavoriteEmoSongs()
{
yield break;
}
C # 언어는이 메서드를 호출 할 때 빈 열거자를 반환합니다. 따라서 언어 디자인 (따라서 프로그래머의 기대)에 따라 빈 컬렉션을 반환해야합니다.
답변
빈은 훨씬 더 소비자 친화적입니다.
빈 열거 형을 구성하는 명확한 방법이 있습니다.
Enumerable.Empty<Element>()
답변
상황에 따라 의미 적으로 올바른 값을 반환해야한다고 생각합니다. “항상 빈 컬렉션을 반환합니다”라는 규칙은 약간 단순 해 보입니다.
예를 들어, 병원 시스템에서 지난 5 년간의 모든 이전 입원 목록을 반환해야하는 기능이 있다고 가정합니다. 고객이 병원에없는 경우 빈 목록을 반환하는 것이 좋습니다. 그러나 고객이 입학 양식의 해당 부분을 비워두면 어떻게됩니까? “빈 목록”과 “답변 없음”또는 “모름”을 구별하려면 다른 값이 필요합니다. 예외를 던질 수는 있지만 반드시 오류 조건은 아니며 정상적인 프로그램 흐름에서 벗어날 수있는 것은 아닙니다.
나는 0과 무응답을 구분할 수없는 시스템에 종종 좌절했습니다. 시스템에서 숫자를 입력하도록 요청한 횟수가 0이고 0을 입력하면이 필드에 값을 입력해야한다는 오류 메시지가 표시됩니다. 방금 했어요 : 0을 입력했습니다! 그러나 대답이없는 것과 구별 할 수 없기 때문에 0을 허용하지 않습니다.
손더스에 대한 답변 :
예, “사람이 질문에 대답하지 않았습니다”와 “답이 0이었습니다”사이에 차이가 있다고 가정합니다. 그것이 내 대답의 마지막 단락의 요점이었습니다. 많은 프로그램들이 “알지 못함”을 공란 또는 제로와 구별 할 수 없으며, 이는 잠재적으로 심각한 결함으로 보입니다. 예를 들어 1 년 정도 전에 집을 쇼핑하고있었습니다. 나는 부동산 웹 사이트에 갔고 가격이 $ 0 인 많은 주택이 나열되었습니다. 나에게 꽤 좋은 소리 : 그들은이 집을 무료로 제공하고 있습니다! 그러나 슬픈 현실은 그들이 가격에 들어 가지 않았다는 것이 확실합니다. 이 경우에, 당신은 말할 수 있습니다. 음, 명백하게 0은 그들이 가격을 입력하지 않았다는 것을 의미합니다. 아무도 집을 무료로주지 않을 것입니다. ” 그러나이 사이트는 또한 여러 도시의 평균 주택 가격과 판매 가격을 나열했습니다. 평균에 0이 포함되어 있지 않은지 궁금해 할 수 없으므로 일부 장소의 평균이 잘못되었습니다. 즉, 평균 $ 100,000는 얼마입니까? $ 120,000; “몰라”? 기술적으로 대답은 “모름”입니다. 우리가 실제로보고 싶은 것은 $ 110,000입니다. 그러나 우리가 얻을 수있는 것은 $ 73,333이며, 이는 완전히 잘못되었을 것입니다. 또한 사용자가 온라인으로 주문할 수있는 사이트에서이 문제가 발생한 경우 어떻게해야합니까? (부동산은 아닐 것입니다 만, 다른 많은 제품들에서 그 일을했다고 확신합니다.) “가격이 아직 지정되지 않았습니다”가 “무료”로 해석되기를 정말로 원하십니까? 따라서 일부 장소의 평균이 잘못되었습니다. 즉, 평균 $ 100,000는 얼마입니까? $ 120,000; “몰라”? 기술적으로 대답은 “모름”입니다. 우리가 실제로보고 싶은 것은 $ 110,000입니다. 그러나 우리가 얻을 수있는 것은 $ 73,333이며, 이는 완전히 잘못되었을 것입니다. 또한 사용자가 온라인으로 주문할 수있는 사이트에서이 문제가 발생한 경우 어떻게해야합니까? (부동산은 아닐 것입니다 만, 다른 많은 제품들에서 그 일을했다고 확신합니다.) “가격이 아직 지정되지 않았습니다”가 “무료”로 해석되기를 정말로 원하십니까? 따라서 일부 장소의 평균이 잘못되었습니다. 즉, 평균 $ 100,000는 얼마입니까? $ 120,000; “몰라”? 기술적으로 대답은 “모름”입니다. 우리가 실제로보고 싶은 것은 $ 110,000입니다. 그러나 우리가 아마 얻을 수있는 것은 $ 73,333이며, 이는 완전히 잘못되었을 것입니다. 또한 사용자가 온라인으로 주문할 수있는 사이트에서이 문제가 발생한 경우 어떻게해야합니까? (부동산은 아닐 것입니다 만, 다른 많은 제품들에서 그 일을했다고 확신합니다.) “가격이 아직 지정되지 않았습니다”가 “무료”로 해석되기를 정말로 원하십니까? 그것은 완전히 잘못된 것입니다. 또한 사용자가 온라인으로 주문할 수있는 사이트에서이 문제가 발생한 경우 어떻게해야합니까? (부동산은 아닐 것입니다 만, 다른 많은 제품들에서 그 일을했다고 확신합니다.) “가격이 아직 지정되지 않았습니다”가 “무료”로 해석되기를 정말로 원하십니까? 그것은 완전히 잘못된 것입니다. 또한 사용자가 온라인으로 주문할 수있는 사이트에서이 문제가 발생한 경우 어떻게해야합니까? (부동산은 아닐 것입니다 만, 다른 많은 제품들에서 그 일을했다고 확신합니다.) “가격이 아직 지정되지 않았습니다”가 “무료”로 해석되기를 정말로 원하십니까?
두 가지 기능을 가진 RE, “있는가?” “그렇다면 무엇입니까?” 그렇습니다, 당신은 확실히 그렇게 할 수 있지만, 왜 당신은 원합니까? 이제 호출 프로그램은 하나 대신 두 번 호출해야합니다. 프로그래머가 “any”를 호출하지 않으면 어떻게됩니까? “무엇입니까?” ? 프로그램이 잘못된 0을 반환합니까? 예외를 던져? 정의되지 않은 값을 반환 하시겠습니까? 더 많은 코드, 더 많은 작업 및 더 많은 잠재적 오류를 만듭니다.
내가 볼 수있는 유일한 이점은 임의의 규칙을 준수 할 수 있다는 것입니다. 이 규칙에 따르는 데 따르는 이점이 있습니까? 그렇지 않다면 왜 귀찮게합니까?
Jammycakes에 대한 답변 :
실제 코드의 모양을 고려하십시오. 질문에 C #이 있다고 말했지만 Java를 작성하면 실례합니다. 내 C #은 매우 선명하지 않으며 원칙은 동일합니다.
널 리턴으로 :
HospList list=patient.getHospitalizationList(patientId);
if (list==null)
{
// ... handle missing list ...
}
else
{
for (HospEntry entry : list)
// ... do whatever ...
}
별도의 기능으로 :
if (patient.hasHospitalizationList(patientId))
{
// ... handle missing list ...
}
else
{
HospList=patient.getHospitalizationList(patientId))
for (HospEntry entry : list)
// ... do whatever ...
}
실제로 널 리턴이있는 줄이 하나 또는 두 줄이 적기 때문에 호출자에게 더 많은 부담이되지 않습니다.
DRY 문제를 만드는 방법을 모르겠습니다. 전화를 두 번 실행해야하는 것은 아닙니다. 리스트가 존재하지 않을 때 항상 똑같은 일을하고 싶었다면, 호출자가하지 않고 get-list 함수로 처리를 푸시 할 수 있기 때문에 호출자에 코드를 넣는 것은 DRY 위반 일 수 있습니다. 그러나 우리는 거의 항상 똑같은 일을하고 싶지 않습니다. 처리 할 목록이 있어야하는 함수에서 누락 된 목록은 처리를 중단 할 수있는 오류입니다. 그러나 편집 화면에서는 아직 데이터를 입력하지 않은 경우 처리를 중단하고 싶지 않습니다. 데이터를 입력하도록하겠습니다. 따라서 “목록 없음”처리는 발신자 수준에서 어떤 방식 으로든 수행되어야합니다. 그리고 우리가 null을 반환하거나 별도의 함수로 수행하는지 여부는 더 큰 원칙과 아무런 차이가 없습니다.
물론, 호출자가 널을 점검하지 않으면 널 포인터 예외로 인해 프로그램이 실패 할 수 있습니다. 그러나 별도의 “get any”기능이 있고 호출자가 해당 기능을 호출하지 않고 “get list”기능을 맹목적으로 호출하면 어떻게됩니까? 예외가 발생하거나 실패하는 경우 null을 반환하고 확인하지 않은 경우와 거의 동일합니다. 빈 목록을 반환하면 잘못되었습니다. “요소가없는 목록이 있습니다”와 “목록이 없습니다”를 구별하지 못했습니다. 사용자가 가격을 입력하지 않은 경우 가격을 0으로 반환하는 것과 같습니다. 잘못되었습니다.
컬렉션에 추가 속성을 첨부하는 것이 어떻게 도움이되는지 모르겠습니다. 발신자는 여전히 확인해야합니다. null을 확인하는 것보다 낫습니까? 다시 말하지만, 최악의 상황은 프로그래머가 확인을 잊고 잘못된 결과를 제공하는 것입니다.
프로그래머가 “값이 없다”는 의미의 null의 개념에 익숙하다면 null을 반환하는 함수는 놀라운 일이 아닙니다. 별도의 기능을 갖는 것이 “놀라운”문제에 가깝다고 생각합니다. 프로그래머가 API에 익숙하지 않은 경우 데이터없이 테스트를 실행하면 때로는 null을 반환한다는 것을 빨리 알게됩니다. 그러나 그러한 기능이있을 수 있고 문서를 확인하고 문서가 완전하고 이해 가능한 것이 아니라면 다른 기능의 존재를 어떻게 발견 할 수 있을까요? 나는 두 가지를 모두 호출하고 알고 있어야하는 두 가지 기능보다는 항상 의미있는 응답을 제공하는 하나의 기능을 원할 것입니다.
답변
빈 컬렉션이 의미 적으로 의미가 있다면 그것이 반환하는 것을 선호합니다. 빈 모음을 반환하면 GetMessagesInMyInbox()
“받은 편지함에 실제로 메시지가 없습니다”라는 메시지가 표시되지만 반환 null
하면 목록이 어떻게 표시되어야하는지 알 수없는 데이터가 충분하지 않다는 것을 알려주는 데 유용 할 수 있습니다.