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

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

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

if (!data.Equals(null))

и

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

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

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 ответов


это не 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());
}

это определенно не хорошо. Я могу представить, что вы положили его туда, чтобы вы могли взломать отладчик, все еще находясь внутри метода, и в этом случае игнорировать этот абзац. В противном случае, не поймать исключения ни за что. И если вы это сделаете, перестройте их, используя just 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"

правда

False


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

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


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

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

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

в C# 7 лучшее

if (obj is null) ...

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

для не равных вы можете 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-объект сам по себе равен null.

есть еще одна проблема с вашим кодом: вы используете ref-ключевое слово, что означает, что данные аргумента не могут быть нулевыми! 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 во-первых, но это другое дело, тем более, что в данном конкретном случае вы делаете исключение.

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


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

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

isnull(object.check.it)

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

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

обновление (другой способ) обновленный 08/31/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
  }
}