Проверка, является ли объект нулевым в С#

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

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

if (!data.Equals(null))

и

if (data != null)

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

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

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

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

Ответ 1

Это не 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;.

Ответ 2

С# 6 имеет монадическую проверку нуля:)

перед:

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

после

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

Ответ 3

в С# 7 лучшим является

if (obj is null)...

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

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

Ответ 4

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

Try:

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;

}

Ответ 5

[Отредактировано, чтобы отобразить подсказку @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'

True

False

Ответ 6

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

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

Ответ 7

Проблема в этом случае заключается не в том, что data имеет значение null. Дело в том, что dataList сам по себе является нулевым.

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

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

Ответ 8

В дополнение к @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 //
   }

Ответ 9

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

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

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

Также не рекомендуется использовать generics с типом `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) {
        //...
      }
    }

Ответ 10

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

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

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

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

Ответ 11

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

Ответ 12

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

Пример: объект1 является объектом класса

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

Ответ 13

Я просто следовал методу, которому мы обычно следовали в сценарии Java. Чтобы преобразовать объект в строку, а затем проверить, являются ли они пустыми.

var obj = new Object();
var objStr = obj.ToString();
if (!string.IsNullOrEmpty(objStr)){
  // code as per your needs
}