オブジェクトが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を回避するためにオブジェクトに対するそれ以上の処理を防ぐ方法は?)
data
がnull
であるのではなく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;
を使ってそれらを再スローします。
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;
}
c#7では最高が
if (obj is null)
...
これは、オブジェクトによって定義されている==または!=を無視します(もちろんそれらを使用したいのでなければ...)
等しくない場合はif (!(obj is null))
(醜い)ができます
[@ 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
いいえ、!=
を使用してください。 data
が実際にnullの場合、あなたのプログラムはNullReferenceException
に対してEquals
メソッドを呼び出そうとした結果としてnull
でクラッシュするでしょう。また、参照の等価性を特に確認したい場合は、Equals
がどのように実装されているのかわからないので、Object.ReferenceEquals
メソッドを使用する必要があります。
初期化しないでdataList
がnullであるため、プログラムはクラッシュしています。
この場合の問題は、data
がnullであることではありません。 dataList
自体がnullです。
dataList
を宣言した場所で、新しいList
オブジェクトを作成してそれを変数に割り当てる必要があります。
List<object> dataList = new List<object>();
@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 //
}
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;
}
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) {
//...
}
}
他の人が既に指摘しているように、それはdata
ではなく、dataList
、つまりnull
です。それに加えて...
catch
-throw
はアンチパターンであり、ほとんどの場合、それを見るたびにスローしたくなる。 doOtherStuff()
が呼び出すものの奥深くで何かがうまくいかないことを想像してください。返されるのは、Exception
オブジェクトであり、AddData()
のthrow
でスローされます。スタックトレース、呼び出し情報、状態、問題の実際の原因を示すものは一切ありません。ただし、デバッガーを切り替えて、未処理の例外ではなく、スローされた例外でブレークするように切り替えた場合を除きます。例外をキャッチして再スローするだけの場合とにかく、特にtryブロックのコードが自明ではない場合は、自分(および同僚、現在と未来)に好意的ですtry
-catch
ブロック全体を破棄します。確かに、throw;
は他の選択肢よりも優れていますが、それでも自分(またはコードのバグを修正しようとしている人)に完全に不要な頭痛を与えています。これは、スローされた例外オブジェクトに関連する何かを行う catchブロック内である限り、try-catch-throw自体が必ずしも悪であると言うことではありません。
そもそもException
をキャッチする潜在的な問題がありますが、特にこの特定のケースでは例外をスローするため、それは別の問題です。
もう少し危険な点は、参照渡しであるため、data
が関数の実行中に値を変更する可能性があることです。そのため、nullチェックはパスする可能性がありますが、コードが値を処理する前に、おそらくnull
に変更されます。これが懸念事項であるかどうか(それはそうではないかもしれませんが)、私は肯定的ではありませんが、注意する価値があるようです。
あなたがクラスのオブジェクトを作成しているときはいつでも、あなたはそのオブジェクトがnullであるかどうか以下のコードを使ってチェックしなければなりません。
例:object1はクラスのオブジェクト
void myFunction(object1)
{
if(object1!=null)
{
object1.value1 //If we miss the null check then here we get the Null Reference exception
}
}
私は、通常Javaスクリプトで従う方法に従うだけです。オブジェクトを文字列に変換してから、それらがnullかどうかを確認します。
var obj = new Object();
var objStr = obj.ToString();
if (!string.IsNullOrEmpty(objStr)){
// code as per your needs
}