Проверка, является ли объект нулевым в С#
Я хотел бы предотвратить дальнейшую обработку объекта, если он равен нулю.
В следующем коде я проверяю, является ли объект нулевым:
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
}