由于我了解到不建议实现ICloneable
(因为它不区分深度复制和浅层复制),我正在尝试确定是将其实现为抽象还是接口。
我觉得我的实现在很大程度上保持不变,例如二进制深度拷贝和MemberwiseClone
浅拷贝,所以为此,我觉得抽象方法将是理想的。然而,我的理解也是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 {}
我肯定会让它成为一个接口。原因是,接口应该是非常通用的,这就是为什么我们可以实现多个接口。如果你想编写一些锅炉板代码,那么没有什么可以阻止你同时利用接口和抽象类。
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 */ }
}
我原以为创建一个接口是最好的方法,但后来我发现了这个问题和第一个答案。这是一个很好的克隆方法,但我认为这可能与自定义扩展方法配合得很好,所以我根据第一篇文章和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();
}
}
基于两个链接的代码样本的具有扩展方法的类
//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);
}
}
}
最后是克隆对象的调用
derived d = new derived();
derived d2 = d.MyCloneExtension<derived>();