2016-05-13 10 views
5

C#でコピーコンストラクタを使用したディープクローンメソッドを実装しました。それが動作することを確認するために、私はオブジェクトとそれがクローンのシリアル化の結果を比較することによってそれをテストしています。シリアライゼーションは一般的なオブジェクトTの観点から行われます。私は具体的なオブジェクトの観点からも試してみましたが、同じ結果を得ています。C#でオリジナルオブジェクトの内容を変更するシリアライズ

私は、次のコードは正常に動作します

private byte[] ObjectToBytes(T obj) 
{ 
    BinaryFormatter formatter = new BinaryFormatter(); 
    using (MemoryStream stream = new MemoryStream()) 
    { 
     formatter.Serialize(stream, obj); 
     stream.Seek(0, SeekOrigin.Begin); 
     return stream.ToArray(); 
    } 
} 

バイト配列にオブジェクトをシリアル化するための方法を持っています。

T original = this.GetNewThing(); 
T clone = original.DeepClone(); 

// serialize after cloning 
byte[] originalBytes = ObjectToBytes(original); 
byte[] cloneBytes = ObjectToBytes(clone); 

bool equal = true; 
for (int i = 0; i < originalBytes.Length; i++) 
{ 
    if(originalBytes[i] != cloneBytes[i] 
    { 
     equal = false; 
     break; 
    } 
} 
equal == true; // True! 

しかし、オブジェクトをシリアル化する順序を切り替えると、バイト配列はもはや等しくなりません。

// serialize before cloning 
T original = this.GetNewThing(); 
byte[] originalBytes = ObjectToBytes(original); 

T clone = original.DeepClone(); 
byte[] cloneBytes = ObjectToBytes(clone); 

bool equal = true; 
for (int i = 0; i < originalBytes.Length; i++) 
{ 
    if(originalBytes[i] != cloneBytes[i] 
    { 
     equal = false; 
     break; 
    } 
} 
equal == true; // False! 

なぜシリアル化の順序がこれに影響しますか?それはBinaryFormatterまたはMemoryStreamオブジェクトと関係がありますか?

EDIT:

はここで深いcloneメソッドが

public MyClass DeepClone() 
{ 
    return new MyClass(this); 
} 

と、それは、オブジェクトが決して複合体である。この

protected MyClass(MyClass myClass) 
{ 
    if (myClass == null) 
     throw new ArguementNullException("myclass"); 

    this.number = myClass.Number; 
    this.number2 = myClass.Number2; 
    this.number3 = myClass.Number3; 
} 

のようなルックスを使用して、コンストラクタのようになります。コピーされるすべての値は値型なので、参照する必要のある型はありません。

+6

DeepCloneメソッドを投稿してください。おそらく問題があります –

+0

オブジェクトの複雑さに関係する可能性があります - これをチェックしてください:http://stackoverflow.com/questions/5017274/binaryformatter-and-deserialization-complex -objects – Clay

+0

完全な「MyClass」を見る必要があるかもしれないと思う。また、それは状態を持たないので、なぜ 'ObjectToBytes'は静的ではなくプライベートなインスタンスメソッドですか? LinqPadに貼り付けられた完全なサンプルコードをフォーマットすることができれば役に立ちそうです。 –

答えて

4

DeepClone、またはそれを順番に呼び出して何かをホープ、あなたのソースオブジェクトの状態を変更しているようです。

+0

DeepCloneは、ストリームを最初にアクセスされるまで設定されません。バイト配列を作成する前にクローンを作成すると、両方のプロパティがディープクローンの間に初期化されるため、これは問題ありません。クローン作成前にバイト配列を作成しても、このプロパティは初期化されず、初期化された値はシリアル化されません(プロパティは値型なので、デフォルト値が選択されます)。 – Danny

1

あなたは次のようにObjectToBytes方法変更する必要があります。

private byte[] ObjectToBytes(Object obj) 
    { 
     if(obj == null) 
      return null; 

     BinaryFormatter bf = new BinaryFormatter(); 
     using(MemoryStream ms = new MemoryStream()) { 
      bf.Serialize(ms, obj); 

      return ms.ToArray(); 
     } 
    } 

はそれが

+0

あなたはこれがどのように役立つと思いますか説明できますか? – adv12

+0

@ adv12 .ToArrayの前にストリームの位置を変更するのは悪い習慣であるためです。それは試みですが、私はDeepCloneの実装を見たいと思います。 – RobertoB

+0

私のコードで 'Seek'への不要な呼び出しを削除しました。それは問題を解決しませんでした。それを取り除いても何の問題も起きなかったので、私はそれを残しておきます。 – Danny