C# 实现自定义克隆/复制功能:抽象还是接口?
据我所知,不建议实现C# 实现自定义克隆/复制功能:抽象还是接口?,c#,interface,abstract-class,icloneable,C#,Interface,Abstract Class,Icloneable,据我所知,不建议实现ICloneable(),我正在尝试确定是应该将其实现为抽象还是接口 我觉得我的实现在很大程度上会保持不变,例如a和a,因此为此,我觉得一个抽象方法将是理想的。然而,我的理解是C#不做多重继承,因此如果我需要使用另一个抽象类,那么我就不能再使用它了 在这种情况下,我觉得实现自定义的ICloneable(例如ICustomCloneable)将是更好的选择,但是如果实现在许多类中实际上是相同的,我觉得我没有充分利用代码重用 也就是说,在我的可克隆类中,使用接口来保持抽象继承的清
ICloneable
(),我正在尝试确定是应该将其实现为抽象还是接口
我觉得我的实现在很大程度上会保持不变,例如a和a,因此为此,我觉得一个抽象方法将是理想的。然而,我的理解是C#不做多重继承,因此如果我需要使用另一个抽象类,那么我就不能再使用它了
在这种情况下,我觉得实现自定义的ICloneable
(例如ICustomCloneable
)将是更好的选择,但是如果实现在许多类中实际上是相同的,我觉得我没有充分利用代码重用
也就是说,在我的可克隆类中,使用接口来保持抽象继承的清晰性是否有效?还是有其他方法可以做到这一点
或者,一个抽象实现另一个抽象是否有效(读:不臭)?这可能是我的猜测,因为要绕过阻止我实现CloneCapable类和另一个抽象的单一继承,但听起来可能有问题。e、 g:
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); }
}
公共接口ICustomCloneable
{
T浅镜();
T DeepCopy();
}
公共抽象类CustomCloneable ICustomCloneable,其中T:class
{
公共T ShallowCopy(){返回ShallowCopy(this);}
public T DeepCopy(){返回DeepCopy(this);}
//静态助手
公共静态对象浅拷贝(T obj){/*样板实现*/}
公共静态对象DeepCopy(T obj){/*样板文件实现*/}
}
公共类ClassA:CustomCloneable{/*使用样板功能*/}
公共类ClassB:其他类,ICustomCloneable
{
//使用静态帮助器实现ICustomCloneable
public ClassB ShallowCopy(){return CustomCloneable.ShallowCopy(this);}
public ClassB DeepCopy(){return CustomCloneable.DeepCopy(this);}
}
我在这里用过泛型,但没有理由你需要。。。甚至不这样做也是可取的。这种方法允许您编写样板代码,但不受其束缚:
公共类ClassC:ICustomCloneable
{
public ClassC ShallowCopy(){/*为ClassC*/}执行特殊克隆
public ClassC DeepCopy(){/*为ClassC*/}执行特殊克隆
}
我认为创建一个界面是一条可行之路,但后来我找到了问题和第一个答案。这是一种很好的克隆方法,但我认为这可能与a非常匹配,因此我根据第一篇文章中的代码和MS帮助页面上的代码编写了fallowing代码:
要玩的一些类:
[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);
}
}
}
//扩展方法必须在静态类中定义
公共静态类扩展
{
//这是扩展方法。
//第一个参数采用“this”修饰符
//并指定为其定义方法的类型。
公共静态T MyCloneExtension(此T)
{
//此函数中的代码是从中复制的https://stackoverflow.com/questions/78536/deep-cloning-objects-in-c-sharp
如果(!typeof(T).IsSerializable)
{
抛出新ArgumentException(“类型必须可序列化。”,“源”);
}
//不要序列化空对象,只需返回该对象的默认值
if(Object.ReferenceEquals(t,null))
{
返回默认值(T);
}
IFormatter formatter=新的BinaryFormatter();
Stream=新的MemoryStream();
使用(流)
{
序列化(流,t);
stream.Seek(0,SeekOrigin.Begin);
返回(T)格式化程序。反序列化(流);
}
}
}
最后是一个克隆对象的调用
derived d = new derived();
derived d2 = d.MyCloneExtension<derived>();
derived=new-derived();
派生d2=d.MyCloneExtension();
非常有洞察力,我很感激。
derived d = new derived();
derived d2 = d.MyCloneExtension<derived>();