1

C#/.NET でシリアル化に問題があり、1 つのストリームで同じオブジェクトへの複数の参照をシリアル化すると、逆シリアル化後にこれらの参照が等しくなくなります。デフォルトのバイナリ シリアル化を使用しています。私をつまずかせるコードは次のとおりです。

Check ck1 = new Check();
Check ck2 = new Check();
ck1.Numbers = new int[] { 11, 12, 13 };
ck2.Numbers = ck1.Numbers;
Console.WriteLine(ReferenceEquals(ck1.Numbers, ck2.Numbers));
FileStream fs = new FileStream("d:\\deleteme-check3.txt", FileMode.Create, FileAccess.Write);
BinaryFormatter oos = new BinaryFormatter();
oos.Serialize(fs, ck1);
oos.Serialize(fs, ck2);
fs.Flush();
fs.Close();
fs = new FileStream("d:\\deleteme-check3.txt", FileMode.Open, FileAccess.Read);
oos = new BinaryFormatter();
Check ck3 = (Check)oos.Deserialize(fs);
Check ck4 = (Check)oos.Deserialize(fs);
Console.WriteLine(ReferenceEquals(ck3.Numbers, ck4.Numbers));

宣言は

[Serializable]
class Check
{
  public int[] Numbers = new int[] { 0, 1, 2 };
}

このコードを実行するTrueと、 とFalse. True私は、私が使用できる機能を探していますTrue

注 #1: と の使用に関する参照をチェックして見ましDataContractSerializerMarshalByRefObjectが、これらの機能をこの問題に適用する方法がわかりません。

注 #2: 独自のカスタム シリアライゼーション ロジックを記述できることは承知していますが、それは避けて、代わりにデフォルトのシリアライゼーションを使用したいと考えています。たとえば、Java でデフォルトのシリアル化を使用するTrueTrue、このシナリオでは と が得られ、.NET で同様のツールを探しています。

4

2 に答える 2

3

これは単に起こりません。参照保持セマンティクスは、Serialize/への 1 回の呼び出しに対してのみ有効ですDeserialize。必要なものを取得するには、ある種のラッパーを使用する必要があります。

[Serializable]
public class HazTwo {
   public Check First {get;set;}
   public Check Second {get;set;}
}

次にシリアル化します。

var obj = new HazTwo { First = ck1, Second = ck2 };
oos.Serialize(fs, obj);

そして逆シリアル化します:

var newObj = (HazTwo)oos.Deserialize(fs);
var ck3 = newObj.First;
var ck4 = newObj.Second;

-のわずかな例外を除いて、Serailizeまたはのいずれかへの個別の呼び出し間で参照 ID が保持されることはありませんが、配列は を実装しないため、これはかなり意味がありません。DeserializeIObjectReferenceIObjectReference

率直に言って、次のいずれかを行うことをお勧めします。

  • ラッパーオブジェクトを使用して、参照を保持する必要があるスコープに対して単一のSerialize/呼び出しのみが有効になるようにしますDeserialize
  • これに依存しない代替設計を見つける

また、通常は過剰使用しないように人々にアドバイスしている脚注を追加する必要がありますBinaryForamtter-通常、コードのバージョン間で反復するときに、非常に多くの人々がデータを失ったり混乱したりするのを見てきました。変更することはあまり受け入れられません。

于 2013-09-15T08:17:56.733 に答える