C#でオブジェクトがnullかどうかを確認する


226

オブジェクトがnullの場合、それ以上処理されないようにしたいと思います。

次のコードで、オブジェクトがnullかどうかを次のいずれかで確認します。

if (!data.Equals(null))

そして

if (data != null)

しかし、私は受信NullReferenceExceptiondataList.Add(data)。オブジェクトがnullの場合、if-statementに入る必要はありません!

したがって、これがオブジェクトが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を回避するためにオブジェクトでの以降の処理を防ぐにはどうすればよいですか?)


13
また、使用すべきthrow e;throw new Exception(e.ToString());
ニックス

17
C#!= nullでは、常にnullチェックで使用する必要があります。 .Equalsオブジェクトがnullの場合、常に例外がスローされます。
Kyle Trauberman

42
@Nix:throw e;あまり良くありません。throw;、一方で...
Jon

4
@developer:e.ToString()エラーメッセージだけでなく、すべてのメッセージInnerExceptionsとスタックトレースを含む文字列を生成します。つまり、これは非常に太い例外メッセージのようなものです。(正しく!)この情報を保存し、それがどこにあるかを保持したい場合は、単にを使用しますthrow;
Jon

14
現在、try / catchは何もしません。誰もが「スロー」を使用するだけだと言っていますが、例外を除いて何もせずに再スローする場合は、なぜtry / catchブロックがあるのでしょうか。通常、例外をキャッチして適切に処理したり、リソースをクリーンアップしたり( "finally"句を使用した方がよい)、例外を再スローする前に何らかのログを記録したりします。これらはこのコードでは発生していないため、try / catchはまったく必要ありません。
David Peterson

回答:


252

それdataではありませんがnull、ですdataList

で作成する必要があります

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

さらに良い:それはフィールドなので、それを作りますprivate。そして、あなたを妨げるものがなければ、それも作りますreadonly。ただ良い練習です。

さておき

nullをチェックする正しい方法はif(data != null)です。この種のチェックは、参照タイプのユビキタスです。さえNullable<T>等価演算子を表現するより便利な方法であることが優先されますnullable.HasValueNULLかどうかをチェックするとき。

あなたが行う場合はif(!data.Equals(null))、あなたが取得しますNullReferenceException場合data == null。そもそもこの例外を回避することが目的だったので、これはコミカルなことです。

あなたもこれをやっています:

catch (Exception e)
{
    throw new Exception(e.ToString());
}

これは間違いなく良くありません。メソッド内にいるときにデバッガーに侵入できるようにそこに配置したと想像できます。この場合、この段落は無視してください。それ以外の場合は、例外を無料でキャッチしないでください。そして、もしそうなら、だけを使用してそれらを再スローしますthrow;


5
この目的でObject.ReferenceEquals(obj、null)確認しました。等価オーバーライドを回避するためですか?
Luca、

2
@LucaPiccioniジェネリックを使用するときに値タイプの不平を防ぐために使用しました:geekality.net/2009/11/13/generics-and-checking-for-null
Svish

4
私は好むnull != data。定数を最初に置くと、骨頭のタイプミスnull = dataが意図しない割り当てではなく、コンパイラエラーになります。(==。でも動作します。)
jpmc26 2014年

6
@ jpmc26:C#if (data = null)では既にコンパイル時エラーが発生しているので、到達するのに数十年かかったとしても、本当にそれを監視する必要はありません。C ++コンパイラでさえ、そのコードの意図しない割り当ての可能性に関する警告を簡単に生成します。
Jon

Luca、テストで 'object'にキャストすることで、等価のオーバーライドを回避することもできます。同様に、この答えは代わりにこれを主張する必要があります: "if((object)data!= null)"等価性がオーバーライドされた場合のエラーを回避します。
DAG 2018年

81

C#> 7.0で使用

if (obj is null) ...

これは、オブジェクトによって定義された==または!=を無視します(もちろん、それらを使用したい場合を除きます...)

nullでない場合if (obj is object)(またはif (!(obj is null))


1
「nullじゃない」ってあるのかな?(Pythonは言うだろうobj is not null
sehe 2018

1
なぜ読みやすいif(obj!= null)よりも優れている
Orn Kristjansson

38
彼らが実装することをif (obj aint null)望みます:(
Nick Bull

10
is n't nullがあるためif (obj is object)
yatskovsky

3
@OrnKristjansson!=と==はオーバーライドできるため。
mitchellJ

61

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;

7
「コメントは5分間しか編集できない」ためですか?何?とにかく...私がそれに到達していたとき..私は表現するためのより良い構文を求めてここに来ました、result = myObject == null ? null : myObject.SomePropertyそしてあなたの例は私に書くように教えましたresult = myObject?.SomeProperty。おとこ!!それは卑劣です。私はまだコーディングが大好きです...
Adam Cox

27

投稿したコードから判断すると、インスタンス化されていないため、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;

}


3
また、追加するだけで、データがnullの場合はクラッシュしません。List<Object>にnullを追加できます。
DaveShaw 2011年

7
しかし、nullで.Equalsを実行しようとすると、例外がスローされます。すべきである!= null
glosrob

@glosrob:ああ!! なんと見落としだ!NullReferenceExceptionはリストからではなくオブジェクトからのものだと思っていました!私はc#を初めて使用するので、c#でnullをチェックする特別な方法があると思いました!
開発者

それも、エドSがカバーしていたのを見ました。
DaveShaw 2011年

1
@DaveShaw:頭を上げてくれてありがとう。後で処理するためにnullオブジェクトが追加されないようにしたいので、引き続きチェックを行います。:)
開発者

19

[@ 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'の比較

本当

誤り


1
実際、私はこれを試してみましたが、「暗黙の利点は、「演算子!=」のように、データのクラスに存在する可能性のあるオーバーライドを無視することです。当てはまらないようです。
ケリーエルトン

9

いいえ、使用する必要があります!=dataが実際にnullの場合NullReferenceExceptionEqualsonメソッドを呼び出そうとした結果、プログラムは単にでクラッシュしnullます。また、参照の等価性を具体的に確認したい場合は、実装Object.ReferenceEquals方法Equalsがわからないため、このメソッドを使用する必要があることにも注意してください。

dataList初期化したことがないので、nullのためプログラムはクラッシュします。


7

この場合の問題は、それdataがnullではないことです。それdataList自体がヌルであるということです。

宣言する場所でdataList、新しいListオブジェクトを作成して変数に割り当てる必要があります。

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

5

@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 //
   }

1
なぜreturn T == null ? true : false;だけではなくreturn T == null;
md2perpe 2018年

1
同意するかどうかわかりません。オブジェクトのメソッドを呼び出してnullかどうかを確認するのは奇妙に見えます。それが拡張メソッドであることを知らなければ、それはnull参照例外をスローすると思います。
Jamie Twells、

ジェイミーが正しいことを完全に確認できます-これは機能しません。私はうんざりするような瞬間があり、同様の拡張メソッドを作成したので知っています。Pコードは常にnull参照例外をスローしましたが、拡張メソッドには絶対に入りません。
James King

実際には、拡張メソッドでそれを行うことができると言いたい...コードに問題があり、改善できる可能性があります!
アリ

nullオブジェクトの拡張メソッドを呼び出すことができます。T(この場合)をnullと比較して注意が必要です。ジェイミーは正しいですが、奇妙に見えます。
Tim Barrass

3

とおりC#8あなたは(との「空の」プロパティのパターンを使用することができ、パターンマッチングをオブジェクトを確保するために)あるないはnull:

if (obj is { })
{
    // 'obj' is not null here
}

このアプローチは、「オブジェクトが何かのインスタンスを参照する場合」(つまり、nullでない場合)を意味します。

これは次の逆と考えることができます。 if (obj is null)...。オブジェクトが何かのインスタンスを参照していない場合、trueを返します。

C#8.0のパターンの詳細については、こちらをご覧ください


3

とおりC#9あなたが行うことができます

if (obj is null) { ... }

nullではない使用

if (obj is not object) { ... }

この動作をオーバーライドする必要がある場合は==!=それに応じて使用してください。


2

ジェフリー・L・ホイットレッジは正しいです。`dataList´-Object自体がnullです。

コードには別の問題もあります。refキーワードを使用しているため、引数データをnullにすることはできません。MSDNは言う:

refパラメーターに渡される引数は、最初に初期化する必要があります。これはoutとは異なり、引数は渡される前に明示的に初期化する必要はありません。

タイプが「オブジェクト」のジェネリックを使用することもお勧めできません。ジェネリックスは、ボックス化/ボックス化解除を回避し、型の安全性も確保する必要があります。共通の型が必要な場合は、メソッドをジェネリックにします。最後に、コードは次のようになります。

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

他の人がすでに指摘したように、dataそうdataListではありませんnull。それに加えて...

catch- throwアンチパターンであり、ほとんどの場合、私はそれを見るたびに投げたくなります。doOtherStuff()呼び出すもののどこかで何かがうまくいかないと想像してください。返されるのはExceptionthrowin でスローされるオブジェクトだけですAddData()。スタックトレース、呼び出し情報、状態、問題の実際の原因を示すものはありません。デバッガーを切り替えて、例外を処理せずにスローされた例外で中断するように切り替えた場合を除きます。例外をキャッチしてそれを何らかの方法で再スローするだけの場合、特にtryブロックのコードがなんらかの方法で重要でない場合は、自分自身(および同僚、現在および将来)に好意を示し、全体を破棄しますtry-catchブロックを。確かにthrow;代替案よりも優れていますが、あなたはまだ完全に不要な頭痛をあなた自身に与えています(または他の誰かがコードのバグを修正しようとしています)。これは、スローされた例外オブジェクトに関連することを行う限り、try-catch-throw自体が必ずしも悪であると言っているのではありません。、catchブロックの内部。

次に、キャッチの潜在的な問題があります Exception、最初、これは別の問題です。特に、この特定のケースでは例外をスローするためです。

少し危険以上に私を襲うもう1つのことdataは、参照渡しであるため、関数の実行中に値が変更される可能性があることです。したがって、nullチェックはパスする可能性がありますが、コードが値を使用して何かを実行する前に、値が変更されnullます。これが懸念事項であるかどうかはわかりませんが(懸念されないかもしれません)、注意する価値があるようです。


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

使用する:

isnull(object.check.it)

条件付き使用:

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

更新(別の方法)2017年8月31日更新。コメントをありがとう。

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

5
cond ? true : false;はと完全に同等condです。これは何も追加しません。
lericson

申し訳ありませんが、関数をチェックするとブール値を返す必要があります。私は形式主義をやっています。もう一度確認してください
ホセオルテガ2017

3
彼はreturn T == null;ブール値も返すことを意味します!
MQoder 2017年

私は彼が言っていることを知っています。TY
ホセ・オルテガ

1
return T == null ? true : false;単に使用する代わりにreturn T == null;
md2perpe

1

クラスのオブジェクトを作成するときはいつでも、以下のコードを使用してオブジェクトがnullかどうかを確認する必要があります。

例:object1はクラスのオブジェクトです

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

0

私は通常、Javaスクリプトで従う方法に従いました。オブジェクトを文字列に変換してから、それらがnullかどうかを確認します。

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

0

私はもっ​​とシンプル(ポジティブな方法)にしましたが、うまくいくようです。

あらゆる種類の「オブジェクト」は少なくともオブジェクトなので


    if (MyObj is Object)
    {
            //Do something .... for example:  
            if (MyObj is Button)
                MyObj.Enabled = true;
    }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.