位置:首頁 > 軟件操作教程 > 編程開發(fā) > C# > 問題詳情

C# 深度復(fù)制

提問人:劉團(tuán)圓發(fā)布時(shí)間:2020-12-07

    通過下面的GetCopy()方法,介紹了如何使用受保護(hù)的方法System.Object.MemberwiseClone()進(jìn)行淺度復(fù)制。

public class Cloner 

{

    public int Val;

    public Cloner{int newVal) => Val = newVal; 

    public object GetCopy() => MemberwiseClone();

}

假定有一些引用類型的字段,而不是值類型的字段(例如,對象):

public class Content

{

    public int Val;

}

public class Cloner 

{

    public Content MyContent = new Content();

    public Cloner(int newVal) => MyContent.Val s newVal;

    public object GetCopy() => MemberwiseClone();

}

此時(shí),通過GetCopyO得到的淺度復(fù)制包括一個(gè)字段,它引用的對象與源對象相同。以下代碼使用這個(gè)Cloner類來說明淺度復(fù)制引用類型的結(jié)果:

Cloner mySource = new Cloner(5);

Cloner myTarget = (Cloner)mySource.GetCopy();

WriteLine($"myTarget.MyContent.Val = {myTarget-MyContent.Val}"); 

mySource.MyContent.Val =2;

WriteLine($"myTarget.MyContent.Val = (myTarget .MyContent.Val}");

    第4行把一個(gè)值賦給mySource.MyContent.Val,它是源對象中公共字段MyContent的公共字段Val。這也改變了 myTarget.MyContent.Val 的值。這是因?yàn)?mySource.MyContent 引用了與 myTargetMyContent 相同的對象實(shí)例。上述代碼的輸出結(jié)果如下:

    myTarget.MyContent.Val = 5 

    myTarget.MyContent.Val = 2

為解決這個(gè)問題,需要執(zhí)行深度復(fù)制。修改上面的GetCopyO方法就可以進(jìn)行深度復(fù)制,但最好使用.NET Framework的標(biāo)準(zhǔn)方式:實(shí)現(xiàn)ICloneable接口,該接口有一個(gè)Clone()方法;這個(gè)方法不帶參數(shù),返回一個(gè)object類型的結(jié)果,其簽名和上面使用的GetCopy()方法相同。

為修改上面的類,可使用下面的深度復(fù)制代碼:

public class Content 

{

    public int Val;

}

public class Cloner : ICloneable

{

    public Content MyContent = new Content 0;

    public Cloner(int newVal) => MyContent.Val = newVal;

    public object Clone()

    {

        Cloner clonedCloner = new Cloner(MyContent.Val); 

        return clonedCloner;

    }

}

其中使用包含在源Cloner對象中的Content對象(MyContent)的Val字段,創(chuàng)建了一個(gè)新對象Cloner。這個(gè)字段是一個(gè)值類型,所以不需要深度復(fù)制。

使用與上面類似的代碼來測試淺度復(fù)制,但用CloneO替代GetCopy(),得到如下結(jié)果:

    myTarget.MyContent.Val = 5 

    myTarget,MyContent.Val = 5

這次包含的對象是獨(dú)立的。注意有時(shí)在比較復(fù)雜的對象系統(tǒng)中,調(diào)用Clone()是一個(gè)遞歸過程。例如,如果Cloner類的MyContent字段也需要深度復(fù)制,就要使用下面的代碼:

public class Cloner : ICloneable 

{

    public Content MyContent = new Content();

    ...

    public object Clone()

    {

        Cloner clonedCloner = new Cloner(); 

        clonedCloner.MyContent = MyContent.Clone(); 

        return clonedCloner;

    }

}

這里調(diào)用了默認(rèn)的構(gòu)造函數(shù),以便簡化創(chuàng)建新對象Cloner的語法。為使這段代碼能正常工作,還需要在 Content 類上實(shí)現(xiàn) ICloneable 接口。

繼續(xù)查找其他問題的答案?

相關(guān)視頻回答
回復(fù)(0)
返回頂部