Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/308.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 实现自定义克隆/复制功能:抽象还是接口?_C#_Interface_Abstract Class_Icloneable - Fatal编程技术网

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>();