2010-06-04 4 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() я всегда мог проверить, является ли нулевой текущий элемент списка или я просто не мог предполагаю, что человек, использующий этот класс не есть отличная идея установить записи в null.

Итак, в конце концов, вопросы заканчиваются: чья ошибка является исключением NullReferenceException в этом случае? Является ли это ошибкой разработчика класса, не проверяя все на нуль (что сделало бы код вообще - не только в этом классе - более сложным), или это ошибка пользователя этого класса, поскольку установка записи List в значение null doesn ' действительно ли смысл? Я бы обычно не проверял значения для null, за исключением некоторых действительно особых случаев. Это плохой стиль или де-факто стандарт/стандарт в практике?

Я знаю, что, вероятно, нет окончательного ответа на этот вопрос, я просто не хватает опыта для такой вещи и поэтому задаюсь вопросом, что другие разработчики думают о таких случаях, и хотят услышать, что сделано в действительности о проверке null (или нет).

+0

спасибо всем за ваши ответы! Я согласен, я должен проверить null/не предлагать возможность установить значение null, если оно не указано.Я, наконец, выбрал ответ Mant101, потому что это просто прост в реализации (подсказка: попробуйте наблюдаемый коллектив - дает больше возможностей без дополнительной работы). Другие ответы тоже были хороши, но я просто мог выбрать только один ;-) Я также посмотрю на контракты с кодом, когда у меня будет больше времени (спасибо MatthewMartin). –

ответ

2

Использование Коллекция <T>, он встроен в настраиваемой обертке для списка <T> вы можете переопределить InsertItem и SetItem и бросить исключение, если элемент является недействительным.

+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 
} 

Если вам не нравится, что, не подвергайте список (который должен подвергаться, как IList<T> BTW), но возвращает список, как коллекция, которая не позволяет null ссылки, которые будут добавлены.

+1

Или LINQly: 'foreach (объект obj в _list.Where (obj => null! = Obj)) {...}'. –

+0

+1 для LINQ! Кроме того, sup. –

7

Прошу прощения, но если ваш код падает не по правилам, это ваша вина. Как насчет того, чтобы вы инкапсулировали список и выставляли метод добавления проверки на нуль, если для остальной части вашего кода это требование? Может быть, ваш класс может реализовать IList, и внутренне хранения списка вы собираетесь обрабатывать - то в методе Add, вы либо просто бросить NullArgumentException или игнорировать null и продолжить ...

+3

+1 для «инкапсулировать список», если вы разрабатываете API, не ленитесь. –

0

Вы не должны доверять пользователю не делать что-то подобное. Иногда запись списка будет иметь значение null. Это происходит. Я постараюсь и поймаю его, когда это возможно. Если вы раскрываете список, всегда есть вероятность, что будет иметься нулевая ссылка, поэтому вы должны учитывать это.

Это не ваша вина как таковая, но не имеет значения, действительно ли это виноват пользователь - вас будут обвинять.

+0

Всегда лучше проверять перед использованием переменной вместо того, чтобы полагаться на try/catch. Попытка разыменовать нулевую ссылку всегда является предупреждаемой ошибкой программиста – dbemerlin

1

Если вы разрешите null s внутри списка, вам необходимо их проверить. Если вы хотите назначить «вину» здесь, то это класс, а не пользователи этого класса. Было бы просто через некоторые геттеры и сеттеры предотвращать null от каждого внесения его в список, если они не принадлежали ему.

1

Если параметр List для NULL не имеет смысла для использования класса, то ошибка лежит в дизайнере класса, который несет ответственность за предотвращение этой операции над классом.

0

Это вина человека, который пытается использовать Список.Вы всегда должны предположить, что он может быть нулевым, и поэтому вы должны его проверить.

Это относится к Оборонительному программированию и тому, как вы должны защищать свой код от того, что делают другие люди.

Code Complete в главе 8 рассматривается в этой концепции.

1

Это зависит от того, что вы хотите сделать со списком в doSomeWorkWithTheList() и что вы будете делать, если значение равно null.

Я бы либо проверил значение null, либо выбросил исключение самостоятельно (с сообщением типа «Недопустимое значение списка, null не разрешено») или не разрешать нулевые значения, создавая подкласс Collection<>, который выдает, если кто-то использует AddItem с нулевое значение.

Предоставляя API, вы также предоставляете договор. Если в контракте указано, что «нулевые значения не разрешены», то пользователь вашего API не несет ответственности за то, чтобы он был недействительным, и ваша ответственность за соблюдение контракта.

1

Если вы не хотите нулей в списке, вы где-нибудь выбросите исключение. Вопрос в том, где? Когда пользователь пытается добавить в список или когда вы пытаетесь его обработать?

Я бы выбрал ArgumentException в точке, которую потребитель класса пытался добавить в список, так как это то, что позволяет им добавлять элемент, если вы не можете работать с ним в любом случае. Но вы захотите выбросить исключение. Не позволяйте потребителю предполагать, что все работает только потому, что они не были проинформированы иначе.

1

Просто фильтровать список, чтобы избежать NREs, это плохая практика, он скрывает ошибки в клиентском коде. Код связан с неисправностью без какого-либо хорошего способа диагностики причины. Пусть он бомбит.

Предоставление объекта коллекции для клиентского кода для участия в вечеринке тоже не очень хорошая практика. Вывести свой класс из IList<object>есть объект?). Вы передадите методы IList частному List<object> в своем классе. Но вы можете переопределить индекс и реализовать метод Add, чтобы убедиться, что код клиента не помещает нули в коллекцию. Если это действительно необходимо.

0

Add code contracts. Затем вы можете проверить наличие нулей при запуске метода, возврате значения и через out с помощью проверки инварианта. Затем, в зависимости от того, какую версию визуальной студии у вас есть, вы можете проверить время компиляции и время выполнения.

0

Мне действительно не нравится вставлять нули в коллекции любого вида, кроме массивов.

Кажется, у меня много разных плакатов. Для меня любой, кто вставляет нуль в коллекцию, которая является свойством какого-либо другого объекта, заслуживает того, что он получает позже.

Когда я закодировал свою пользовательскую хэш-таблицу (System.Generic.Dictionary имеет некоторые проблемы, в которые я не буду входить), я решил сделать поиск возврата null на не найден. Поскольку я не вставляю нули, это облегчило мою жизнь.

Смежные вопросы