избегать исключений нулевой ссылки - PullRequest
21 голосов
/ 22 декабря 2009

Очевидно, что подавляющее большинство ошибок в коде являются исключениями нулевых ссылок. Существуют ли какие-либо общие методы, позволяющие избежать появления ошибок нулевых ссылок?

Если я не ошибаюсь, я знаю, что в таких языках, как F #, невозможно иметь нулевое значение. Но это не вопрос, я спрашиваю, как избежать ошибок нулевых ссылок в таких языках, как C #.

Ответы [ 15 ]

2 голосов
/ 22 декабря 2009

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

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

1 голос
/ 08 марта 2016

Решение с простым кодом

Вы всегда можете создать структуру, которая помогает отлавливать ошибки нулевых ссылок ранее, помечая переменные, свойства и параметры как «не обнуляемые». Вот пример, концептуально смоделированный после того, как Nullable<T> работает:

[System.Diagnostics.DebuggerNonUserCode]
public struct NotNull<T> where T : class
{
    private T _value;

    public T Value
    {
        get
        {
            if (_value == null)
            {
                throw new Exception("null value not allowed");
            }

            return _value;
        }
        set
        {
            if (value == null)
            {
                throw new Exception("null value not allowed.");
            }

            _value = value;
        }
    }

    public static implicit operator T(NotNull<T> notNullValue)
    {
        return notNullValue.Value;
    }

    public static implicit operator NotNull<T>(T value)
    {
        return new NotNull<T> { Value = value };
    }
}

Вы будете использовать очень похоже на то же самое, что и Nullable<T>, за исключением того, что вы хотите сделать прямо противоположное - не допустить null. Вот несколько примеров:

NotNull<Person> person = null; // throws exception
NotNull<Person> person = new Person(); // OK
NotNull<Person> person = GetPerson(); // throws exception if GetPerson() returns null

NotNull<T> неявно преобразуется в T, поэтому вы можете использовать его где угодно. Например, вы можете передать объект Person методу, который принимает NotNull<Person>:

Person person = new Person { Name = "John" };
WriteName(person);

public static void WriteName(NotNull<Person> person)
{
    Console.WriteLine(person.Value.Name);
}

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

Person person = GetPerson();

public static NotNull<Person> GetPerson()
{
    return new Person { Name = "John" };
}

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

Person person = (NotNull<Person>)GetPerson();

public static Person GetPerson()
{
    return new Person { Name = "John" };
}

Комбинация с удлинителем

Объедините NotNull<T> с методом расширения, и вы сможете охватить еще больше ситуаций. Вот пример того, как может выглядеть метод расширения:

[System.Diagnostics.DebuggerNonUserCode]
public static class NotNullExtension
{
    public static T NotNull<T>(this T @this) where T : class
    {
        if (@this == null)
        {
            throw new Exception("null value not allowed");
        }

        return @this;
    }
}

А вот пример того, как его можно использовать:

var person = GetPerson().NotNull();

GitHub

Для справки, я сделал код выше доступным на GitHub, вы можете найти его по адресу:

https://github.com/luisperezphd/NotNull

0 голосов
/ 17 июля 2017

NullReferenceException может быть показано, когда метод не найден в сборке, для ex m0 = mi.GetType (). GetMethod ("TellChildToBeQuiet"), где сборкой является SportsMiniCar, mi является экземпляром MiniVan, а TellChildToBeQuiet является методом в сборке. Мы можем избежать этого, увидев, что эта сборка версии 2.0.0.0, содержащая вышеуказанный метод, помещена в GAC. пример: вызов методов с параметрами: `

enter code here

using System;
using System.Rwflection;
using System.IO;
using Carlibraries;
namespace LateBinding
{
public class program
{
   static void Main(syring[] args)
   {
         Assembly a=null;
         try
         {
              a=Assembly.Load("Carlibraries");
         }
         catch(FileNotFoundException e)
         {
               Console.Writeline(e.Message);
               Console.ReadLine();
               return;
         }
         Type miniVan=a.GetType("Carlibraries.MiniVan");
         MiniVan mi=new MiniVan();
         mi.TellChildToBeQuiet("sonu",4);
         Console.ReadLine();
       }
   }
   }

Не забудьте обновить MiniSportsCar Assembly с помощью TellChildToBeQuiet (строка ChildName, int count)

0 голосов
/ 08 марта 2016

Инструменты, которые могут помочь

Есть также несколько библиотек, которые могут помочь. Контракты Microsoft Code были упомянуты выше.

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

Также есть PostSharp , который позволит вам просто использовать такие атрибуты:

public void DoSometing([NotNull] obj)

Сделав это и сделав PostSharp частью вашего процесса сборки, obj будет проверен на null во время выполнения. См .: PostSharp проверка на ноль

В проекте Fody для создания кода имеется плагин для , реализующий нулевую защиту.

0 голосов
/ 10 июня 2015

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

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

Другим решением является функциональный тип Option , представляющий собой набор с нулем или одним элементом. Таким образом, у вас будет возможность пропустить операцию, которая не может быть выполнена.

Это параметры, которые могут помочь вам написать код, не имея нулевых ссылок и нулевых проверок.

...