Кажется, у меня возникли серьезные проблемы с NullReferenceExceptions - PullRequest
6 голосов
/ 12 июля 2010

Недавно я занимаюсь разработкой программного обеспечения, которое анализирует и отображает информацию XML с веб-сайта.Достаточно просто, верно?

Я получаю НАГРУЗКИ исключений NullReferenceException.Например, этот метод:

private void SetUserFriends(List<Friend> list)
{
    int x = 40;
    int y = 3;

    if (list != null)
    {
        foreach (Friend friend in list)
        {
            FriendControl control = new FriendControl();
            control.ID = friend.ID;
            control.URL = friend.URL;
            control.SetID(friend.ID);
            control.SetName(friend.Name);
            control.SetImage(friend.Photo);

            control.Location = new Point(x, y);
            panel2.Controls.Add(control);

            y = y + control.Height + 4;
        } 
    }
}

Мне пришлось обернуть уродливое как грех Если вокруг фактического цикла foreach, чтобы предотвратить исключение.

Я чувствую, что просто ставлю бинтына спущенном колесе вместо того, чтобы фактически решить проблему.Есть ли способ, которым я могу решить эту проблему?Может быть, книгу, которую я должен прочитать о шаблонах программирования или нет?

Действительно, я заблудился.Я, вероятно, задаю неправильные вопросы.

Ответы [ 6 ]

15 голосов
/ 12 июля 2010

Звучит так, как будто вы не знаете, что делать, если вы получили неверные параметры в ваших методах.Нет ничего плохого в том, что вы делаете сейчас, но более распространенный шаблон - проверка параметров в заголовке вашего метода, исключение, если они не соответствуют вашим ожиданиям:

if (list == null)
{
    throw new ArgumentNullException(list);
}

Это общий шаблон защитного программирования - проверьте, чтобы данные, которые вы предоставляете, проходили базовые проверки работоспособности.

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

4 голосов
/ 12 июля 2010

Я, вероятно, получу отрицательную оценку от толпы "нет многократного выхода", но я обычно делаю это с простой проверкой прямо в начале метода:

if (list == null || list.Count == 0) return;

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

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

2 голосов
/ 12 июля 2010

Кажется, что вы ищете защитное программирование и проверку параметров.

Как уже говорили другие, простая проверка параметров будет работать для вас:

if (list == null)
    throw new ArgumentNullException("list");

В качестве альтернативы, еслиВы устали постоянно писать подобные проверки для каждого параметра, вы можете проверить одну из многих библиотек исполнения предварительных условий .NET с открытым исходным кодом.Мне нравится CuttingEdge.Conditions .

Таким образом, вы можете использовать что-то вроде этого:

Condition.Requires(list, "list").IsNotNull();

Однако, создавая предварительное условие, как любое из вышеупомянутыхпросто укажет, что ваш метод не принимает значения NULL. Ваша проблема все еще будет существовать в том, что вы передаете пустые значения в метод!Чтобы это исправить, вам нужно изучить, что вызывает ваши методы, и выяснить, почему нулевые объекты передаются.

1 голос
/ 12 июля 2010

Помимо выдачи исключений ArgumentNullException, есть также нечто, называемое «Шаблон нулевого объекта», которое можно использовать, если вы хотите, чтобы передавал ноль, например, чтобы указать, что что-то существует, но не хочу явно проверять наличие нулей. По сути, это класс-заглушка, который реализует тот же интерфейс, но его методы обычно либо пусты, либо возвращают достаточно, чтобы сделать их завершенными. http://en.wikipedia.org/wiki/Null_Object_pattern

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

0 голосов
/ 13 ноября 2016

Вы действительно задаете не тот вопрос. Правильный вопрос: «действительно ли null представляет неправильный ввод или флаг, который означает X».

До тех пор, пока ненулевые ссылочные типы не будут добавлены к языку и будут использовать различные API, у вас есть выбор сделать это явным в коде или позволить исключениям с нулевой ссылкой помочь вам найти, где ожидание нарушено, и затем исправить данные / код так или иначе.

0 голосов
/ 12 июля 2010

Я бы досрочно возвратил (или забросил бы исключение InvalidArgumentException), если задан неверный ввод.

Например:

private void SetUserFriends(List<Friend> list) 
{ 
    if (list == null) 
        return;

    /* Do stuff */
}

В качестве альтернативы вы можете использовать общий шаблон объединения нулей:

private void SetUserFriends(List<Friend> list) 
{ 
    list = list ?? new List<Friend>();

    /* Do Stuff */
}
...