2013-08-05 2 views
0

ICloneable (due to the fact that it does not differentiate between Deep Copy or Shallow Copy)을 구현하는 것이 권장되지 않는다는 것을 알게되었으므로이를 추상화 또는 인터페이스로 구현해야하는지 판단하려고합니다.사용자 정의 복제/복사 기능 구현 : 추상화 또는 인터페이스?

내 구현이 거의 동일하게 유지 될 것이라고 생각합니다. binary deep copyMemberwiseClone shallow copy, 그래서 결국 나는 추상적 인 방법이 이상적이라고 느꼈다. 그러나, 내 이해는 또한 C#이 복수 상속을하지 않기 때문에, 다른 추상 클래스를 사용해야 할 경우 더 이상 할 수 없습니다.

그런 경우에는 사용자 정의 ICloneable (예 : ICustomCloneable)을 사용하는 것이 더 나은 옵션이 될 수 있다고 생각하지만, 구현이 여러 클래스에서 사실상 동일하다면 코드 재사용을 적절하게 활용하지 못하고있는 것처럼 느껴집니다. .

사실 복제 가능 클래스에서 더 중요한 것들에 대해 추상 상속을 유지하기위한 인터페이스를 사용하는 것이 유효합니까? 아니면 다른 방법이 있습니까?

또는 다른 초록을 구현하기 위해 초록이 유효합니까 (읽기 : 아닌지)? 이것은 CloneCapable 클래스와 다른 추상을 구현하지 못하게하는 단일 상속을 해결하는 것으로 추측되지만, 의심 스러울 수도 있습니다. 예 :

public abstract class CloneCapable 
{ 
    public object ShallowCopy() 
    { 
    // implementation 
    } 

    public object DeepCopy() 
    { 
    // implementation 
    } 
} 

public abstract class ClassA : CloneCapable {} 

// abstract-abstract since I can't do ClassB : ClassA, CloneCapable 
public abstract class ClassB : ClassA {} 

답변

2

나는 확실히이 인터페이스를 만들 것입니다. 그 이유는 인터페이스가 매우 일반이기 때문에 여러 인터페이스를 구현할 수 있습니다. 작성하고자하는 보일러 - 플레이트 코드가 있다면 인터페이스와 추상 클래스를 모두 사용하는 것을 막을 수있는 방법은 없습니다.

public interface ICustomCloneable<T> 
{ 
    T ShallowCopy(); 
    T DeepCopy(); 
} 

public abstract class CustomCloneable<T> ICustomCloneable<T> where T : class 
{ 
    public T ShallowCopy() { return ShallowCopy(this); } 
    public T DeepCopy() { return DeepCopy(this); } 

    // static helpers 
    public static object ShallowCopy(T obj) { /* boilerplate implementation */ } 
    public static object DeepCopy(T obj) { /* boilerplate implementation */ } 
} 


public class ClassA : CustomCloneable<ClassA> { /* Use boilerplate functionality */ } 
public class ClassB : SomeOtherClass, ICustomCloneable<ClassB> 
{ 
    // implement ICustomCloneable using static helpers 
    public ClassB ShallowCopy() { return CustomCloneable<ClassB>.ShallowCopy(this); } 
    public ClassB DeepCopy() { return CustomCloneable<ClassB>.DeepCopy(this); } 
} 

여기에 제네릭을 사용했지만 사용자가 필요하지는 않습니다 ... 그렇지 않을 수도 있습니다. 이 방법을 사용하면 상용구 코드를 작성하지만,에 의해 묶여 하지 않을 수 있습니다 :

public class ClassC : ICustomCloneable<ClassC> 
{ 
    public ClassC ShallowCopy() { /* Do special cloning for ClassC */ } 
    public ClassC DeepCopy() { /* Do special cloning for ClassC */ } 
} 
+0

큰 통찰력, 감사합니다. – Arclight

0

내가 인터페이스를 생성하는 갈 수있는 방법이라고 생각했다, 그러나 나는 this 질문 최초의 해답을 발견했다. 그것은 복제를 할 수있는 좋은 방법이지만, 나는 그 코드가 Custom Extension Method으로 매우 잘 돌아갈 것이라고 생각하여 첫 번째 게시물과 MS 도움말 페이지의 코드를 기반으로 휴면 코드를 작성했습니다.

일부 클래스 객체

에게 복제

[Serializable] 
public abstract class Base 
{ 
    public abstract int m1(); 
} 

[Serializable] 
public class derived : Base 
{ 
    public int a = 42; 
    public override int m1() 
    { 
     throw new NotImplementedException(); 
    } 
} 

모두 linkes

//Extension methods must be defined in a static class 
public static class StringExtension 
{ 
    // This is the extension method. 
    // The first parameter takes the "this" modifier 
    // and specifies the type for which the method is defined. 
    public static T MyCloneExtension<T>(this T t) 
    { 
     // Code in this function was copied from https://stackoverflow.com/questions/78536/deep-cloning-objects-in-c-sharp 
     if (!typeof(T).IsSerializable) 
     { 
      throw new ArgumentException("The type must be serializable.", "source"); 
     } 

     // Don't serialize a null object, simply return the default for that object 
     if (Object.ReferenceEquals(t, null)) 
     { 
      return default(T); 
     } 

     IFormatter formatter = new BinaryFormatter(); 
     Stream stream = new MemoryStream(); 
     using (stream) 
     { 
      formatter.Serialize(stream, t); 
      stream.Seek(0, SeekOrigin.Begin); 
      return (T)formatter.Deserialize(stream); 
     } 
    } 
} 

마지막 호출에서 코드 샘플을 기반으로 확장 메서드와 클래스 : 함께 플레이3210
derived d = new derived(); 
derived d2 = d.MyCloneExtension<derived>();