카피
17728 단어 C#
1. 우선 가장 멍청한 방법이다. 전설의'인공 복사'는 인용된 모든 값 대상과 값 특징을 가진string 대상을 일일이 새로운 대상에게 부여하는 것이다. 이런 방식은 코드량이 너무 많고 유지하기가 상당히 번거롭기 때문에 사용하지 않으면 안 된다.
2.System.Object는 '얕은 표' 복사를 위한 보호 방법인 MemberwiseClone을 제공합니다.이 방법은 '보호됨' 단계로 표시되어 있기 때문에, 계승 클래스나 이 클래스 내부에서만 접근할 수 있습니다.
public class A
{
public string rr { get; set; }
public string tt { get; set; }
public A ShallowCopy()
{
return (A)this.MemberwiseClone();
}
}
3. 서열화와 반서열화 방식을 사용한다. 이런 방식은 깊이 있는 복사를 실현할 수 있지만 모기를 잡는 냄새가 난다. 또한 밖에서 인용할 때 만들어진 메모리스트림 흐름을 닫는 것을 반드시 기억해야 한다.
public static object Clone(object o,out MemoryStream ms)
{
BinaryFormatter bf = new BinaryFormatter();
ms = new MemoryStream();
bf.Serialize(ms,o);
ms.Seek(0, SeekOrigin.Begin);
return bf.Deserialize(ms);
}
4. 한 외국인이 쓴 블로그에서http://www.codeproject.com/Articles/3441/Base-class-for-cloning-an-object-in-C), 반사하는 방법으로 이 문제를 해결했다.그는 BaseObject 클래스를 썼는데 만약에 우리가 이 클래스를 계승하면 깊이 있는 복사를 실현할 수 있다. 다음은 그의 실현 방법이다.
ICloneable 인터페이스를 실현하는 기본 행위를 가진 추상적인 클래스를 만듭니다. 기본 행위란 클래스의 모든 필드를 복사하기 위해 다음 라이브러리 함수를 사용합니다.
1. 클래스의 모든 필드를 옮겨다니며 ICloneable 인터페이스를 지원하는지 확인합니다.
2. ICloneable 인터페이스가 지원되지 않으면 다음 규칙에 따라 설정합니다. 즉, 필드가 값 유형이면 복사하고 인용 유형이면 복사 필드는 대상을 가리킨다.
3. ICloneable를 지원할 경우 클론 객체의 복제 방법을 사용하여 설정합니다.
4. 필드가 IEnumerable 인터페이스를 지원한다면 IList나 IDirectionary 인터페이스를 지원하는지 확인하고 지원하면 ICloneable 인터페이스를 지원하는지 반복해서 집합합니다.
우리가 해야 할 일은 모든 필드가 ICloneable 인터페이스를 지원하도록 하는 것이다.
다음은 테스트 결과입니다.
public class MyClass : BaseObject
{
public string myStr =”test”;
public int id;
}
public class MyContainer : BaseObject
{
public string name = “test2”;
public MyClass[] myArray= new MyClass[5];
public class MyContainer()
{
for(int i=0 ; i<5 ; i++)
{
this.myArray[I] = new MyClass();
}
}
}
static void Main(string[] args)
{
MyContainer con1 = new MyContainer();
MyContainer con2 = (MyContainer)con1.Clone();
con2.myArray[0].id = 5;
}
con2에서 MyClass 실례에서 첫 번째 요소는 5로 바뀌었지만 con1은 변하지 않았다. 즉, 깊은 복사를 실현했다.
BaseObject의 구현:
/// <summary>
/// BaseObject class is an abstract class for you to derive from.
/// Every class that will be dirived from this class will support the
/// Clone method automaticly.<br>
/// The class implements the interface ICloneable and there
/// for every object that will be derived <br>
/// from this object will support the ICloneable interface as well.
/// </summary>
public abstract class BaseObject : ICloneable
{
/// <summary>
/// Clone the object, and returning a reference to a cloned object.
/// </summary>
/// <returns>Reference to the new cloned
/// object.</returns>
public object Clone()
{
//First we create an instance of this specific type.
object newObject = Activator.CreateInstance( this.GetType() );
//We get the array of fields for the new type instance.
FieldInfo[] fields = newObject.GetType().GetFields();
int i = 0;
foreach( FieldInfo fi in this.GetType().GetFields() )
{
//We query if the fiels support the ICloneable interface.
Type ICloneType = fi.FieldType.
GetInterface( "ICloneable" , true );
if( ICloneType != null )
{
//Getting the ICloneable interface from the object.
ICloneable IClone = (ICloneable)fi.GetValue(this);
//We use the clone method to set the new value to the field.
fields[i].SetValue( newObject , IClone.Clone() );
}
else
{
// If the field doesn't support the ICloneable
// interface then just set it.
fields[i].SetValue( newObject , fi.GetValue(this) );
}
//Now we check if the object support the
//IEnumerable interface, so if it does
//we need to enumerate all its items and check if
//they support the ICloneable interface.
Type IEnumerableType = fi.FieldType.GetInterface
( "IEnumerable" , true );
if( IEnumerableType != null )
{
//Get the IEnumerable interface from the field.
IEnumerable IEnum = (IEnumerable)fi.GetValue(this);
//This version support the IList and the
//IDictionary interfaces to iterate on collections.
Type IListType = fields[i].FieldType.GetInterface
( "IList" , true );
Type IDicType = fields[i].FieldType.GetInterface
( "IDictionary" , true );
int j = 0;
if( IListType != null )
{
//Getting the IList interface.
IList list = (IList)fields[i].GetValue(newObject);
foreach( object obj in IEnum )
{
//Checking to see if the current item
//support the ICloneable interface.
ICloneType = obj.GetType().
GetInterface( "ICloneable" , true );
if( ICloneType != null )
{
//If it does support the ICloneable interface,
//we use it to set the clone of
//the object in the list.
ICloneable clone = (ICloneable)obj;
list[j] = clone.Clone();
}
//NOTE: If the item in the list is not
//support the ICloneable interface then in the
//cloned list this item will be the same
//item as in the original list
//(as long as this type is a reference type).
j++;
}
}
else if( IDicType != null )
{
//Getting the dictionary interface.
IDictionary dic = (IDictionary)fields[i].
GetValue(newObject);
j = 0;
foreach( DictionaryEntry de in IEnum )
{
//Checking to see if the item
//support the ICloneable interface.
ICloneType = de.Value.GetType().
GetInterface( "ICloneable" , true );
if( ICloneType != null )
{
ICloneable clone = (ICloneable)de.Value;
dic[de.Key] = clone.Clone();
}
j++;
}
}
}
i++;
}
return newObject;
}
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
WebView2를 Visual Studio 2017 Express에서 사용할 수 있을 때까지Evergreen .Net Framework SDK 4.8 VisualStudio2017에서 NuGet을 사용하기 때문에 패키지 관리 방법을 packages.config 대신 PackageReference를 사용해야...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.