web-dev-qa-db-ja.com

C#でオブジェクトがnullかどうかを調べる

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

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

if (!data.Equals(null))

そして

if (data != null)

しかし、私はdataList.Add(data)NullReferenceExceptionを受け取ります。オブジェクトが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を回避するためにオブジェクトに対するそれ以上の処理を防ぐ方法は?)

178
developer

datanullであるのではなくdataListです。

あなたが作成する必要があります

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

さらに良いことに、それはフィールドなので、それをprivateにします。そして、あなたを妨げるものが何もなければ、それもreadonlyにしてください。ちょうどいい習慣です。

無効かどうかをチェックする正しい方法はif(data != null)です。この種のチェックは参照型にはどこにでもあります。 Nullable<T>でさえも、等価性演算子をオーバーライドして、nullかどうかをチェックするときにnullable.HasValueを表現するより便利な方法になります。

あなたがif(!data.Equals(null))をするならば、あなたはdata == nullならNullReferenceExceptionを得るでしょう。そもそもこの例外を回避することが目標だったので、どちらがコミカルなのか。

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

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

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

220
Jon

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;
46
Jowen

あなたが投稿したコードから判断すると、あなたの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;

}

26
glosrob

c#7では最高が

if (obj is null) ...

これは、オブジェクトによって定義されている==または!=を無視します(もちろんそれらを使用したいのでなければ...)

等しくない場合はif (!(obj is null))(醜い)ができます

20
kofifus

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

本当

False

17
gatopeich

いいえ、!=を使用してください。 dataが実際にnullの場合、あなたのプログラムはNullReferenceExceptionに対してEqualsメソッドを呼び出そうとした結果としてnullでクラッシュするでしょう。また、参照の等価性を特に確認したい場合は、Equalsがどのように実装されているのかわからないので、Object.ReferenceEqualsメソッドを使用する必要があります。

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

9
Ed S.

この場合の問題は、dataがnullであることではありません。 dataList自体がnullです。

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

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

@Jose Ortega answerに加えて、その使用方法の改善 拡張方法

 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 //
   }
4
Ali
  public static bool isnull(object T)
  {
      return T == null ? true : false;
  }

つかいます:

isnull(object.check.it)

条件付き使用:

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

更新(別の方法)2017/08/31を更新しました。コメントありがとう。

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

Jeffrey L Whitledgeは正しいです。あなたの `dataList´-Object自体はnullです。

あなたのコードには別の問題もあります:あなたはref-keywordを使っています。 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) {
        //...
      }
    }
2
DiableNoir

他の人が既に指摘しているように、それはdataではなく、dataList、つまりnullです。それに加えて...

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

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

もう少し危険な点は、参照渡しであるため、dataが関数の実行中に値を変更する可能性があることです。そのため、nullチェックはパスする可能性がありますが、コードが値を処理する前に、おそらくnullに変更されます。これが懸念事項であるかどうか(それはそうではないかもしれませんが)、私は肯定的ではありませんが、注意する価値があるようです。

2
a CVn

あなたがクラスのオブジェクトを作成しているときはいつでも、あなたはそのオブジェクトがnullであるかどうか以下のコードを使ってチェックしなければなりません。

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

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

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

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