0

私は少しコードを書いています、そして私に面倒を与える部分があります。私のコードには次の構造があります。

foreach (Node node in nodes)
{
    try
    {
        bool n = node.previous == null;
    }
    catch (Exception e)
        {
            StreamWriter s = new StreamWriter("error.txt");
            s.WriteLine(e.Message);
            s.WriteLine("-----------");
            s.Close();
        }
}

ここで、Nodeはカスタムタイプであり、node.prev変数もカスタムタイプ(Location)です。これを実行すると、次のエラーログが表示されます。

Object reference not set to an instance of an object.
-----------

ノードがnullではないことを100%確信しています(これはforeach = trueではありません。申し訳ありません!)によって不可能になるはずです。また、次のリストからわかるように、Node.previousは宣言時にnullに設定されています。

public class Node
{
    public Location previous = null;
    public Location location;
    public int distance;
    ...
    ...
}

発生しているこれらの例外をどのように修正できるかわかりません。これを解決する方法についてのアイデアは、もう少しで終わりです。誰かがこれを手伝ってくれますか?

これらはすべて最終的なコードではないことに注意してください、しかし私は重要ではない部分をふるいにかけました!

よろしくお願いします、デルピー

編集:Ricovoxはこの答えで私を解決に助けてくれました、どうもありがとう!

4

6 に答える 6

4

最も可能性の高い問題は、node nullです! 。node一般に、IEnumerableオブジェクト(リストやコレクションなど)には有効なアイテムとしてnullを含めることができるため、foreachステートメントについてはnullを防ぐことはできません。

previousnullの場合、エラーはスローされません(node.prevクラス/構造体が==演算子をオーバーライドしない限り)。

他の人が述べているように、次のことを確認するために次のようなテストを行います。

foreach (Node node in nodes)
{
    bool n;
    try
    {
        if (node == null) 
        {
           n = true; //do something to deal with a null node
        }
        else 
        {
          n = node.previous == null;
        }
    }
    catch (Exception e)
    {
        StreamWriter s = new StreamWriter("error.txt");
        s.WriteLine(e.Message);
        s.WriteLine("-----------");
        s.Close();
    }
}
于 2012-12-18T19:10:25.260 に答える
4

だから私はあなたのコメントに応えて別の答えを投稿しています:

「ノードがnullであることを確認しましたが、そうではありません。」

それが本当なら、ここにいくつかの他のオプションがあります。

  1. node.previousクラス/構造体の定義を見てください。==nullと比較するとエラーをスローするCUSTOM演算子を実装できます。Nullable<T>例として、タイプについて考えてみましょう。HasValueプロパティがfalseの場合にtrueを返すオーバーロードされた==演算子があります(明らかに、これは構造体であるため、真にnullではありませんが、演算子をオーバーロードすると目的の動作が得られます)。これを修正するには、どちらが実行object.ReferenceEquals(node.previous, null)されないかをテストできます。オーバーロードされます。定義を変更するためのアクセス権がある場合はnode.previous、おそらく、nullと比較したときにオーバーロードされた演算子が例外をスローする理由を見つけることができます(明らかにすべきではありません)

  2. nodesnullの可能性があります。その場合、エラーをスローしているのはforeachステートメントです。nodes == nullforeachの前にテストします。

- - - - - - - -編集 - - - - - - - -

Jeppeが指摘したように、(上記のオプション#1での)私のアナロジーは誤解Nullable<T>を招く可能性があります(実際、ポイント自体は正しいものの、議論を混乱させました)。演算子をオーバーライドするという考えをよりよく説明するために==、タイプを示す例を以下に投稿しましたContainer。この型は構造体であるため、それ自体がnullになることはありませんが、単一のValueオブジェクトが含まれています。(この構造体のポイントはContainer、含まれているオブジェクトがnullであっても、nullであるかどうかを気にせずに任意のオブジェクトを操作できることですValue)。==注意すべき主な点は、コンテナをnullと比較した場合、結果はisの場合は真になり、がの場合Valueは真nullではないということです。==演算子はオーバーライドされませんでした(構造体がnullになることはないため)。

public struct Container {
    public object Value { get; set; }
    public bool IsNull { get { return Value == null; } }
    public static bool operator ==(Container x, object y) { return x.Equals(y); }
    public static bool operator !=(Container x, object y) { return !x.Equals(y); }
    public override bool Equals(object obj) {
        if (obj is Container)
            return Value == ((Container)obj).Value;
        return Value == obj;
    }
    public override int GetHashCode() { return Value == null ? 0 : Value.GetHashCode(); }
}

////---------Test----------
var x = new Container { Value = null };
var y = new Container { Value = "hi" };
var z = new Container { Value = null };
Print(x == null); //true 
Print(x == y);    //false
Print(x == z);    //true

そして、オーバーライドがクラスにどのように影響するか疑問に思っている場合に備えて==、クラスを示す別の例を以下に記述しましたBoxContainerBoxオブジェクト自体がnullである場合を処理する必要があることを除いて、構造体に似ています。この場合、オーバーライドの別の驚くべき結果があることに注意してください====2つの参照型は、異なるオブジェクトを参照している場合でも、プロパティが等しい限り、互いに等しく()にすることができValueます。

public class Box {
    public static bool ItemsEqual(object x, object y) {
        object xval, yval;
        xval = x is Box ? (x as Box).Value : x;
        yval = y is Box ? (y as Box).Value : y;
        return xval == yval;
    }
    public object Value { get; set; }
    public bool IsNull { get { return Value == null; } }
    public static bool operator ==(Box x, object y) { return ItemsEqual(x, y); }
    public static bool operator !=(Box x, object y) { return !ItemsEqual(x, y); }
    public override bool Equals(object obj) { return ItemsEqual(this, obj); }
    public override int GetHashCode() { return Value == null ? 0 : Value.GetHashCode(); }
}

////---------Test----------
object n = null;
Box w = null;
Box x = new Box { Value = null };
Box y = new Box { Value = "hi" };
Box z = new Box { Value = "hi" };

Print(w == null);  //true (uses overridden '==' because w is defined as a Box)
Print(w == n);     //true
Print(x == w);     //true 
Print(x == null);  //true 
Print(x == n);     //true 

Print(w == y);    //false
Print(x == y);    //false
Print(y == z);    //true (actual ref's differ, but values are ==)
于 2012-12-18T19:16:58.637 に答える
1

ループの前にnodes例外nullが発生し、例外がキャッチされなかった場合。

メンバーは単純なフィールドであるため、コレクションのメンバーのprevious1つがである可能性があります。あなたはこれを行うことができます:nodenodesnull

foreach (Node node in nodes)
{
  if (node == null)
    throw new Exception("I told you so");
}

編集:わかりました、私が見なかった1つの可能性がありました、そしてそれは==オペレーターの壊れた過負荷でした。通常のオーバーロードを確実に呼び出すには、次のように言います。

foreach (Node node in nodes)
{
  bool n = (object)(node.previous) == (object)null;
}

==(実際には、演算子の片側だけをにキャストするだけで十分ですobject)、または同等に使用しますReferenceEquals

foreach (Node node in nodes)
{
  bool n = object.ReferenceEquals(node.previous, null);
}

ただし、オーバーロードの誤った実装を修正する必要==があります。

元の質問で例外のスタックトレースを投稿した場合、例外がオーバーロードの呼び出しから発生したことは、ここのほとんどのユーザーにとって明らか==でした。したがって、次回は、スタックトレースを調べます。

于 2012-12-18T19:15:00.810 に答える
0

は値型ではないため、nodenullでないことを保証するものは何もありません。Node詳細を教えてください。

于 2012-12-18T19:04:41.940 に答える
0

で始まる行にブレークポイントを設定し、boolノードがnullではないこととノードがnullでないことを確認します。私の推測では、ノードがnullであるか、タイプセーフリストでない場合はnull値が含まれていると思います。

于 2012-12-18T19:05:22.167 に答える
0

ノードがnullではないことを100%確信しています

しかし、ノード内の要素がnullであると100%確信しています!これを試して:

foreach (Node node in nodes)
{
    try
    {
        if(null == node) throw new Exception("This is not expected!");
        bool n = node.previous == null;
    }
    catch (Exception e)
        {
            if(File.Exists("error.txt")) File.Delete("error.txt");
            using(StreamWriter s = new StreamWriter("error.txt")){
            s.WriteLine(e.Message);
            s.WriteLine("-----------");
            s.Close();}
        }
}
于 2012-12-18T19:12:52.807 に答える