Проверка, является ли объект 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 ответов:
это не
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
метод onnull
. Также поймите, что, если вы специально хотите проверить равенство ссылок, вы должны использовать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 } }