2010-06-04 5 views
0

현재 속성을 통해 내부 목록을 노출하는 클래스에서 작업하고 있습니다. 목록은 수정 될 수 있으며 수정할 수 있습니다. 문제는 내부 목록의 항목을 클래스 외부에서 null로 설정할 수 있다는 것입니다.누구의 결함이 NullReferenceException입니까?

내 코드는 실제로 다음과 같습니다

class ClassWithList 
{ 
    List<object> _list = new List<object>(); 

    // get accessor, which however returns the reference to the list, 
    // therefore the list can be modified (this is intended) 
    public List<object> Data 
    { 
     get 
     { 
      return _list; 
     } 
    } 

    private void doSomeWorkWithTheList() 
    { 
     foreach(object obj in _list) 
      // do some work with the objects in the list without checking for null. 
    } 
} 

을 그래서 지금 doSomeWorkWithTheList (에서) 난 항상 현재 목록 항목이 널인지 확인할 수 있습니다 또는 나는이 클래스를 사용하는 사람이하지 않는 것을 asume 단지 수 항목을 null로 설정하는 것이 좋습니다.

그래서 결국 질문이 끝납니다. 누구의 잘못은 NullReferenceException입니까? 클래스 개발자가 null에 대한 모든 것을 검사하지 않는다는 것 (이 코드는 일반적으로이 클래스 에서뿐만 아니라 더 복잡한 것입니다) 또는이 클래스 사용자의 잘못으로 List 항목을 null로 설정하면 ' 정말 말이 되니? 일반적으로 특별한 경우를 제외하고는 null 값을 확인하지 않는 경향이 있습니다. 이것이 잘못된 스타일인가, 아니면 사실상의 표준/표준인가?

아마 이것에 대한 궁극적 인 대답은 없다는 것을 알았습니다. 그런 경험에 대한 충분한 경험이 없으므로 다른 개발자가 그런 사례에 대해 어떻게 생각하는지 궁금해하고 실제로 null을 확인하는 것에 대해 듣고 싶습니다.

+0

답장을 보내 주셔서 감사합니다. 나는 동의한다, 나는 널 위해 점검해야하지만, 그렇지 않다면 널 값을 설정할 수있는 가능성을 제공하지 않는다.마침내 구현하기 쉽기 때문에 Mant101의 답글을 선택했습니다. (힌트 : observablecollection을 시도해보십시오 - 더 많은 작업없이 더 많은 가능성을 제공합니다). 다른 응답도 훌륭했지만 단지 하나만 선택할 수있었습니다 ;-) 나는 더 많은 시간 (MatthewMartin에게 감사드립니다)이있을 때 코드 계약을 살펴볼 것입니다. –

답변

2

는 사용 컬렉션 <T>, 그것은 내장되어 사용자 정의 래퍼는 다음 InsertItem과 SetItem을 무시하고 항목이 null의 경우 예외를 던질 수있는 목록 <T>을 위해.

+0

내 작업에서는이를 ObjectModel.Collection으로 알고 있으며 매우 훌륭하다는 데 동의합니다. – Joshua

7

목록을 노출하면 클래스 사용자가 자유롭게 null 개의 참조를 추가 할 수 있습니다.
사용자가 원하는대로 null 개의 참조를 추가하도록 허용하면 클래스가 목록에서 null 개의 참조를 준비해야합니다.

private void doSomeWorkWithTheList() 
{ 
    foreach(object obj in _list) 
     if (obj != null) 
      // do some work with the object 
} 

당신이 마음에 들지 않으면, (BTW IList<T>로 노출되어야 함) 목록을 표시 할 수 있습니다 만, null 참조를 추가 할 수 없습니다 목록 같은 집합을 반환하지 않습니다.

+1

또는 LINQly :'foreach (object obj in _list.Where (obj => null! = obj)) {...}'. –

+0

+1 LINQ! 또한, sup. –

7

미안하지만, 귀하의 코드가 부당하게 넘어지면, 귀하의 잘못입니다. 목록을 캡슐화하고 나머지 코드에이 요구 사항이있는 경우 null 검사 추가 메소드를 노출하는 방법은 어떻습니까? 어쩌면 당신의 클래스가 IList을 구현할 수 있으며, 내부적으로는 처리하고자하는 목록을 저장 - Add 방법에 다음, 당신은 단지 하나

+3

+1은 "목록을 캡슐화"합니다. API를 설계하는 경우 게으르지 마십시오. –

0

당신은 사용자를 신뢰하지해야 ... NullArgumentException을 던져 또는 null를 무시하고 계속 이런 식으로하지 마라. 경우에 따라 목록 항목이 null로 설정됩니다. 이런 일이 일어난다. 가능할 때마다 나는 그것을 시도하고 붙잡을 것이다. 목록을 노출하는 경우 항상 null 참조가 발생할 가능성이 있으므로이를 고려해야합니다.

귀하의 잘못이 아니지만 실제로는 사용자의 잘못인지 여부는 문제가되지 않습니다. 귀하는 비난받을 것입니다.

+0

try/catch를 사용하는 대신 변수를 사용하기 전에 항상 확인하는 것이 좋습니다. null 참조를 참조 해제하려고하면 항상 피할 수있는 프로그래머 오류가 발생합니다. – dbemerlin

1

null을 허용하려면 해당 항목을 확인해야합니다. 여기에 "책임"을 지정하려면 클래스의 사용자가 아닌이 클래스입니다. 일부 getter 및 setter를 통해 null이 속하지 않으면 목록에 포함되지 않도록하는 것이 간단합니다.

1

List를 NULL로 설정하는 것이 클래스 사용에 적합하지 않은 경우 클래스에서 해당 작업을 방지하는 책임이있는 클래스 디자이너와 결함이 있습니다.

0

목록을 사용하려는 사람의 잘못입니다.당신은 항상 그것이 null이 될 수 있다고 가정해야하므로 그것을 점검해야합니다.

이것은 방어 프로그래밍에 들어가며 다른 사람들이하는 일에서 코드를 보호해야합니다.

Code Complete 8 장의 내용이이 개념에 들어갑니다.

1

이것은 doSomeWorkWithTheList()의 목록으로 수행 할 작업과 값이 null 인 경우 수행 할 작업에 따라 다릅니다.

나는 "유효하지 않은 목록 값, null이 허용되지 않습니다"와 같은 메시지를 사용하여 null을 확인하고 예외를 던집니다. 누군가가 AddItem을 사용하는 경우 throw하는 Collection<>의 하위 클래스를 만들어 null 값을 허용하지 않습니다. null 값.

API를 제공하면 계약을 제공 할 수도 있습니다. 계약서에 "null 값이 허용되지 않습니다"라고되어 있으면 null을 설정하지 않는 것은 API 사용자의 책임이며 계약을 준수 할 책임은 귀하에게 있습니다.

1

목록에서 null을 원하지 않으면 어딘가에서 예외가 발생합니다. 질문은 : 어디서? 사용자가 목록에 추가하려고 할 때 또는 처리하려고 할 때?

클래스 소비자가 목록에 추가하려고했던 시점에 ArgumentException을 던져 버릴 수 있습니다. 어쨌든 함께 작업 할 수 없다면 항목을 추가 할 수있는 지점이 무엇인지 알 수 있습니다. 하지만 예외를 던지기를 원할 것입니다. 소비자가 다르게 알리지 않았기 때문에 모든 것이 제대로 작동한다고 가정하지 마십시오.

1

NRE를 피하기 위해 목록을 필터링하는 것은 나쁜 습관입니다. 클라이언트 코드에 버그가 숨겨집니다. 그 이유를 진단하는 좋은 방법이 없어도 코드는 오작동에 빠질 수 있습니다. 폭탄 투기하자.

파티 용 클라이언트 코드에 대한 콜렉션 객체를 노출하는 것도 좋지 않습니다. IList<object>에서 수업을 생성하십시오 (이 있습니까?). 클래스의 전용 List<object> 필드에 IList의 메서드를 위임합니다. 그러나 인덱서를 재정의하고 Add 메서드를 구현하여 클라이언트 코드가 컬렉션에 null을 넣지 않았는지 확인할 수 있습니다. 정말 필요한 경우.

0

Add code contracts. 그런 다음 메서드 시작, 반환 값 및 불변 검사를 사용하여 out에서 null을 확인할 수 있습니다. 그럼 당신이 가진 Visual Studio의 버전에 따라, 당신은 컴파일 시간과 런타임을 확인할 수 있습니다.

0

나는 어레이가 아닌 다른 종류의 콜렉션에 널 (NULL)을 삽입하는 것을 정말로 좋아하지 않는다.

여기 포스터가 많이 달라 보이는 것 같습니다. 나에게, 다른 객체의 속성 인 컬렉션에 null을 붙이는 사람은 나중에 얻을 수있는 가치가있다.

내 맞춤 해시 테이블을 코딩 할 때 (System.Generic.Dictionary에 몇 가지 문제가 있습니다. 여기서는 다루지 않을 것입니다) 조회를 null을 찾을 수 없도록하기로했습니다. Null을 삽입하지 않았기 때문에 내 인생이 쉬워졌습니다.

관련 문제