Проверка, является ли объект null в C#


Я хотел бы предотвратить дальнейшую обработку объекта, если он равен null.

в следующем коде я проверяю, является ли объект null либо:

if (!data.Equals(null))

и

if (data != null)

однако, я получаю NullReferenceException at dataList.Add(data). Если объект был null, он никогда не должен был даже вводить if-заявление!

таким образом, я спрашиваю, если это правильный способ проверки, если объект null:

public List<Object> dataList;
public  bool AddData(ref Object data)
    bool success = false;
    try
    {
        // I've also used "if (data != null)" which hasn't worked either
        if (!data.Equals(null))
        {
           //NullReferenceException occurs here ...
           dataList.Add(data);
           success = doOtherStuff(data);
        }
    }
    catch (Exception e)
    {
        throw new Exception(e.ToString());
    }
    return success;
}

если это правильный способ проверка, если объект имеет значение null, что я делаю неправильно (как я могу предотвратить дальнейшую обработку объекта, чтобы избежать исключения NullReferenceException)?

12 161

12 ответов:

это не data что это null, а dataList.

вам нужно создать один с

public List<Object> dataList = new List<Object>();

еще лучше: так как это поле, сделать его private. И если вам ничего не мешает, сделайте это также readonly. Просто хорошая практика.

в сторону

правильный способ проверки на ничтожность if(data != null). Этот вид проверки является повсеместным для ссылочных типов; даже Nullable<T> переопределяет оператор равенства, чтобы быть больше удобный способ выражения nullable.HasValue при проверке ничтожности.

если у вас if(!data.Equals(null)) тогда вы получите NullReferenceException если data == null. Что довольно комично, так как избежать этого исключения было целью в первую очередь.

Вы делаете это:

catch (Exception e)
{
    throw new Exception(e.ToString());
}

это определенно не хорошо. Я могу себе представить, что вы положили его туда, чтобы вы могли взломать отладчик, все еще находясь внутри метода, и в этом случае проигнорируйте этот абзац. В противном случае, не ловите исключения ни за что. И если вы это сделаете, перестроить их, используя только throw;.

в C# 6 и монадическом проверку на null :)

перед:

if (points != null) {
    var next = points.FirstOrDefault();
    if (next != null && next.X != null) return next.X;
}   
return -1;

после:

var bestValue = points?.FirstOrDefault()?.X ?? -1;

ваш dataList имеет значение null, поскольку он не был создан, судя по коду, который вы опубликовали.

попробуй:

public List<Object> dataList = new List<Object>();
public  bool AddData(ref Object data)
bool success = false;
try
{
    if (!data.Equals(null))   // I've also used if(data != null) which hasn't worked either
    {
       dataList.Add(data);                      //NullReferenceException occurs here
       success = doOtherStuff(data);
    }
}
catch (Exception e)
{
    throw new Exception(e.ToString());
}
return success;

}

[отредактировано, чтобы отразить подсказку @kelton52]

самый простой способ это сделать object.ReferenceEquals(null, data)

С (null==data) не гарантируется работа:

class Nully
{
    public static bool operator ==(Nully n, object o)
    {
        Console.WriteLine("Comparing '" + n + "' with '" + o + "'");
        return true;
    }
    public static bool operator !=(Nully n, object o) { return !(n==o); }
}
void Main()
{
    var data = new Nully();
    Console.WriteLine(null == data);
    Console.WriteLine(object.ReferenceEquals(null, data));
}

выдает:

сравнение " с 'Nully'

правда

ложные

нет, вы должны использовать !=. Если data на самом деле null, то ваша программа просто рухнет с NullReferenceException в результате попытки вызвать Equals метод on null. Также поймите, что, если вы специально хотите проверить равенство ссылок, вы должны использовать Object.ReferenceEquals способ, как вы никогда не знаете, как Equals была реализована.

ваша программа рушится, потому что dataList имеет значение null, поскольку вы никогда не инициализируете его.

проблема в данном случае не в том data равно null. Он заключается в том, что dataList сам по себе равен нулю.

в том месте, где вы объявляете dataList вы должны создать новый List объект и присвоить его переменной.

List<object> dataList = new List<object>();

в C# 7 лучшее

if (obj is null) ...

это будет игнорировать любые == или != определяется объектом (если, конечно, вы не хотите их использовать ...)

для не равных вы можете if (!(obj is null)) (некрасиво)

кроме @Jose Ortega ответ, его лучше использовать метод расширения

 public static bool IsNull(this object T)
     {
        return T == null;
     } 

и использовать IsNull метод для всех объектов, как:

object foo = new object(); //or any object from any class
if (foo.IsNull())
   {
     // blah blah //
   }

Джеффри л Уитледж прав. Ваш ' dataList-объект сам по себе является нулевым.

есть и другая проблема с вашим кодом: вы используете ref-ключевое слово, что означает, что данные аргумента не могут быть null! MSDN говорит:

аргумент, передаваемый параметр ref должен быть инициализирован. Это отличается от out, чьи аргументы не должны быть явно инициализированы перед их передачей

также не рекомендуется использовать дженерики с типом ' Object. Дженерики должны избегать бокса / распаковки, а также обеспечивать безопасность типа. Если вы хотите, чтобы общий тип сделал ваш метод универсальным. Наконец, ваш код должен выглядеть так:

public class Foo<T> where T : MyTypeOrInterface {

      public List<T> dataList = new List<T>();

      public bool AddData(ref T data) {
        bool success = false;
        try {
          dataList.Add(data);                   
          success = doOtherStuff(data);
        } catch (Exception e) {
          throw new Exception(e.ToString());
        }
        return success;
      }

      private bool doOtherStuff(T data) {
        //...
      }
    }

как уже указывали другие, это не data скорее всего,dataList что это null. В дополнение к этому...

catch -throw это антипаттерн, который почти всегда заставляет меня рвать каждый раз, когда я его вижу. Представьте себе, что что-то идет не так глубоко в чем-то, что doOtherStuff() звонки. Все, что вы получите обратно-это Exception объект, брошенный в throw на AddData(). Нет трассировки стека, нет информации о вызове, нет состояния, вообще ничего, чтобы указать реальный источник проблемы, если вы не войдете и не переключите свой отладчик, чтобы сломать исключение, вызванное, а не исключение необработанное. Если вы ловите исключение и просто повторно бросаете его в любом случае, особенно если код в блоке try каким-либо образом нетривиален, сделайте себе (и своим коллегам, настоящим и будущим) одолжение и выбросьте весь try -catch заблокировать. Конечно,throw; лучше, чем альтернативы, но вы все еще даете себя (или кого-то еще попытка исправить ошибку в коде) совершенно ненужные головные боли. Это не означает, что try-catch-throw обязательно является злом как таковым, пока вы сделать что-то важное с объектом исключения, который был брошен внутри блока catch.

тогда есть потенциальные проблемы ловли Exception во-первых, но это другое дело, тем более что в данном конкретном случае вы бросаете исключение.

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

  public static bool isnull(object T)
  {
      return T == null ? true : false;
  }

использование:

isnull(object.check.it)

условный использовать:

isnull(object.check.it) ? DoWhenItsTrue : DoWhenItsFalse;

обновление (другой способ) обновлено 31.08.2017. Спасибо за комментарий.

public static bool isnull(object T)
{
    return T ? true : false;
}

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

пример: object1-это объект класса

void myFunction(object1)
{
  if(object1!=null)
  {
     object1.value1 //If we miss the null check then here we get the Null Reference exception
  }
}