2017-10-25 5 views
1

以下のオブジェクトをシリアル化すると、Json.Netは自己参照ループを検出し、例外をスローします。参照ループ検出で基準参照が使用されないのはなぜですか?

それは自己参照特性を持つ
  • は、Child
  • それはそれはJSONと思わEquals()GetHashCode()
public class Foo 
{ 
    public int Value { get; set; } 

    public Foo Child { get; set; } 

    public override bool Equals(object obj) => (obj as Foo).Value == this.Value; 

    public override int GetHashCode() => this.Value.GetHashCode(); 
} 

... 

var foo = new Foo { Value = 42, Child = new Foo { Value = 42 } }; 
JsonConvert.SerializeObject(foo); // Throws JsonSerializationException 

上書きします:

クラスは、2つの重要な機能を備えています。 NetはオーバーライドEquals()を使用して参照ループ(デバッグによって確認)。しかしここにはループはありません。

参照参照ループをチェックするために等価性を使用しないのはなぜですか?

私は1つの参照の等価を使用していたEqualityComparer異なっを供給できることを実証a testを見つけましたが、私はそれがデフォルトの動作ではありません理由を知って興味があります。

+0

です。デフォルトで 'Object.Equals(...)'は参照型の参照の等価性をチェックします。あなたはこれをやり直さないようにオーバーライドしました。あなたの平等テストが単一のプロパティに基づいて価値の平等をチェックするので、ループがあると考えています。なぜこれは驚くべきことでしょうか? – Amy

+1

こんにちは@Amy、私は 'Equals()'をオーバーライドするという点は*論理*等価性をチェックすることだと言います。ここでの私の提案は、* reference *ループを検出するために、Json.Netは論理的平等を気にするべきではなく、参照平等のみを考慮する必要があるということです。 –

+0

私はあなたの質問に答えていました。あなたはなぜそうではないのか尋ねました。します。あなたは明示的にそうしないように言いました。価値の平等を具体的に確認する際に、参照平等を期待しないでください。 – Amy

答えて

2

Newtonsoftは、明示的にIssue #401: Object reference equality should be used when checking for circular referencesでこの問題に取り組んだ:

を、私は開発者に等しいをオーバーライドすることでロジックをカスタマイズすることができます、現在の行動を好みます。

さらに、これは大きな変更です。

しかし、その後、後で追加:

を追加EqualityComparerはJsonSerializer 3cc797cに。

この拡張は、設定に上書きする基準ループ検出にobject.Equalsを呼び出すのデフォルトの動作を可能にするJsonSerializerSettings.EqualityComparerのサポートを追加しました:

public IEqualityComparer EqualityComparer { get; set; }

はで使用される等値比較子を取得または設定参照を比較するときはシリアライザ。

関連する問題