Sprawdzanie, czy obiekt jest null w C#

Chciałbym zapobiec dalszemu przetwarzaniu obiektu, jeśli jest null.

W poniższym kodzie sprawdzam czy obiekt jest null przez:

if (!data.Equals(null))

I

if (data != null)

Jednak otrzymuję NullReferenceException w dataList.Add(data). Jeśli obiekt był null, nigdy nie powinien był nawet wprowadzić if-instrukcji!

Dlatego pytam, czy jest to właściwy sposób sprawdzania, czy obiekt jest 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;
}

Jeśli jest to właściwy sposób sprawdzania, czy obiekt jest null, co robię źle (Jak mogę zapobiec dalszemu przetwarzaniu obiektu, aby uniknąć wyjątku NullReferenceException)?

Author: Peter Mortensen, 2011-06-21

12 answers

To nie data to jest null, ale dataList.

Musisz utworzyć jedną z

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

Jeszcze lepiej: skoro to pole, zrób to private. A jeśli nic cię nie powstrzyma, zrób to również readonly. Po prostu dobra praktyka.

Na bok

Poprawnym sposobem sprawdzenia nieważności jest if(data != null). Ten rodzaj sprawdzania jest wszechobecny dla typów referencyjnych; nawet Nullable<T> zastępuje operator równości, aby był wygodniejszym sposobem wyrażania nullable.HasValue podczas sprawdzania nieważność.

Jeśli zrobisz if(!data.Equals(null)) wtedy otrzymasz NullReferenceException Jeśli data == null. Co jest dość komiczne, ponieważ unikanie tego wyjątku było celem na pierwszym miejscu.

Ty też to robisz:

catch (Exception e)
{
    throw new Exception(e.ToString());
}
To zdecydowanie nie jest dobre. Mogę sobie wyobrazić, że umieściłeś go tam tylko po to, aby móc włamać się do debuggera, będąc jeszcze wewnątrz metody, w którym to przypadku Zignoruj ten akapit. W przeciwnym razie nie łap WYJĄTKÓW za nic. A jeśli to zrobisz, przerzuć je używając tylko throw;.
 205
Author: Jon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-20 23:34:27

C # 6 ma monadyczne sprawdzanie null :)

Przed:

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

Po:

var bestValue = points?.FirstOrDefault()?.X ?? -1;
 38
Author: Jowen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-28 08:10:14

Twój dataList jest null, ponieważ nie został utworzony, sądząc po kodzie, który opublikowałeś.

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;

}

 26
Author: glosrob,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-20 22:04:50

[edytowane przez @ kelton52]

Najprostszy sposób to zrobić object.ReferenceEquals(null, data)

Ponieważ {[2] } nie ma gwarancji, że zadziała:

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

Produkuje:

Porównując " z "Nully"

True

False

 16
Author: gatopeich,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-25 08:52:14

Nie, powinieneś używać !=. Jeśli data jest w rzeczywistości null, to twój program po prostu zawiesi się z NullReferenceException w wyniku próby wywołania metody Equals na null. Zdaj sobie również sprawę, że jeśli chcesz sprawdzić równość odniesienia, powinieneś użyć metody Object.ReferenceEquals, ponieważ nigdy nie wiesz, jak Equals została zaimplementowana.

Twój program się zawiesza, ponieważ dataList jest zerowy, ponieważ nigdy go nie inicjalizujesz.

 9
Author: Ed S.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-20 21:51:24

Problemem w tym przypadku nie jest to, że data jest null. Jest to, że dataList sama w sobie jest null.

W miejscu gdzie deklarujesz dataList należy utworzyć nowy obiekt List i przypisać go do zmiennej.

List<object> dataList = new List<object>();
 6
Author: Jeffrey L Whitledge,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-20 21:42:19

W C# 7 najlepsze jest

if (obj is null) ...

To zignoruje any = = or != zdefiniowane przez obiekt (o ile oczywiście nie chcesz ich używać ...)

For not equal you can if (!(obj is null)) (Brzydula)

 6
Author: kofifus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-22 00:27:44

Oprócz @Jose Ortega odpowiedz, its better for use extension method

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

I użyj metody IsNull dla wszystkich obiektów takich jak:

object foo = new object(); //or any object from any class
if (foo.IsNull())
   {
     // blah blah //
   }
 4
Author: combo_ci,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-28 19:31:32

Jeffrey L Whitledge ma rację. Twój " dataList-obiekt sam w sobie jest null.

Jest jeszcze jeden problem z Twoim kodem: używasz słowa kluczowego ref, co oznacza, że dane argumentów nie mogą być null! MSDN says:

Argument przekazany do parametru ref musi być najpierw zainicjowany. Różni się to od out, którego argumenty nie muszą być jawnie inicjalizowane przed ich przekazaniem

Nie jest też dobrym pomysłem używanie generyków z obiektem typu`. Leki generyczne powinny unikać boksu/rozpakowywania, a także zapewnić bezpieczeństwo typu. Jeśli chcesz mieć typ wspólny, stwórz metodę generyczną. Na koniec Twój kod powinien wyglądać tak:

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) {
        //...
      }
    }
 2
Author: DiableNoir,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-21 08:51:07

Jak już zauważyli inni, nie jest to data, ale raczej prawdopodobne dataList, że jest to null. Poza tym...

catch-throw to antypattern, który prawie zawsze sprawia, że chcę wymiotować za każdym razem, gdy go widzę. Wyobraź sobie, że coś idzie nie tak głęboko w czymś, co doOtherStuff() nazywa. Wszystko co dostajesz to Exception obiekt, rzucony na throw w AddData(). Brak śladu stosu, brak informacji o połączeniach, brak stanu, nic, co wskazywałoby prawdziwe źródło problemu, chyba że wejdziesz i Przełącz swój debugger, aby złamać wyjątek wyrzucony, a nie wyjątek nieobsługiwany. Jeśli wyłapujesz wyjątek i po prostu rzucasz go ponownie w jakikolwiek sposób , szczególnie jeśli kod w bloku try jest w jakikolwiek sposób nietrywialny, zrób sobie (i swoim kolegom, obecnym i przyszłym) przysługę i wyrzuć cały try-catch blok. Oczywiście, {[11] } jest lepsze niż alternatywy, ale nadal dajesz sobie (lub komuś innemu próbuje naprawić błąd w kodzie) całkowicie niepotrzebne bóle głowy. Nie oznacza to, że try-catch-throw jest złem per se, o ile robisz coś istotnego z wyjątkiem obiektu, który został wyrzucony {19]} wewnątrz bloku catch.

Potem są potencjalne problemy z łapaniem Exception w pierwszej kolejności, ale to już inna sprawa, zwłaszcza, że w tym konkretnym przypadku rzucasz wyjątek.

Kolejną rzeczą, która wydaje mi się bardziej niż trochę niebezpieczna, jest to, że data może potencjalnie zmienić wartość podczas wykonywania funkcji, ponieważ przechodzisz przez odniesienie. Więc sprawdzenie null może przejść, ale zanim kod zrobi cokolwiek z wartością, zostanie zmieniony-być może na null. Nie jestem pewien, czy jest to problem, czy nie (może nie być), ale wydaje się, że warto na to uważać.

 2
Author: Michael Kjörling,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-21 12:12:16
  public static bool isnull(object T)
  {
      return T == null ? true : false;
  }

Użycie:

isnull(object.check.it)

Użycie warunkowe:

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

Aktualizacja (w inny sposób) zaktualizowano 31/08/2017. Dzięki za komentarz.

public static bool isnull(object T)
{
    return T ? true : false;
}
 2
Author: Jose Ortega,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-31 17:19:07

Podczas tworzenia obiektów klasy musisz sprawdzić, czy obiekt jest null, czy nie używając poniższego kodu.

Przykład: obiekt1 jest obiektem klasy

void myFunction(object1)
{
  if(object1!=null)
  {
     object1.value1 //If we miss the null check then here we get the Null Reference exception
  }
}
 1
Author: user3483639,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-29 18:55:02