是否有一个特定的原因为什么一个通用的 ICloneable<T> 不存在?

它会更加舒适,如果我不会需要转换,它每次我的克隆的东西。

有帮助吗?

解决方案

ICloneable现在被认为是不好的API,因为它没有具体的结果是否是深或浅拷贝。我想这就是为什么他们不提高这个接口。

您也许可以做一个类型的克隆扩展方法,但我认为这将需要一个不同的名字,因为扩展方法比原有的较少的优先级。

其他提示

除了安德烈的答复(我同意,+1) - 当ICloneable的做,你也可以选择明确的实施,使公众Clone()返回一个类型的对象:

public Foo Clone() { /* your code */ }
object ICloneable.Clone() {return Clone();}

当然有具有通用ICloneable<T>一个第二个问题 - 继承

如果我有:

public class Foo {}
public class Bar : Foo {}

和我实现ICloneable<T>,然后我实施ICloneable<Foo>ICloneable<Bar>?您快速启动实施了很多相同的接口... 相比较而言,投...是不是真的那么差?

我要问,到底是什么将你的界面做的比其他的实施呢?接口通常只有有用的,当你投给它(即不该类支持“伊巴尔”),或具有参数或把它制定者(即我采取“IBAR”)。随着ICloneable - 我们在整个框架去,并没有找到一个使用任何地方,比它的实现其他的东西。我们还没有发现在“现实世界”也确实比其他实现它的任何东西的使用(以我们有机会获得〜60000的应用程序)。

现在,如果你只是想强制执行,你希望你的“可复制”对象实现模式,这是一个完全没使用 - 和前进。您也可以决定什么“克隆”对你意味着什么(即深或浅)。然而,在这种情况下,没有必要对我们(BCL)来定义它。我们仅在BCL定义抽象当有需要交换类型为不相关的库之间的抽象实例。

大卫基恩(BCL队)

我想这个问题:“为什么”是不必要的。有很多接口/类/等等,这是非常有用的,但并不是.NET Frameworku碱库的一部分。

不过,主要是你可以自己做。

public interface ICloneable<T> : ICloneable {
    new T Clone();
}

public abstract class CloneableBase<T> : ICloneable<T> where T : CloneableBase<T> {
    public abstract T Clone();
    object ICloneable.Clone() { return this.Clone(); }
}

public abstract class CloneableExBase<T> : CloneableBase<T> where T : CloneableExBase<T> {
    protected abstract T CreateClone();
    protected abstract void FillClone( T clone );
    public override T Clone() {
        T clone = this.CreateClone();
        if ( object.ReferenceEquals( clone, null ) ) { throw new NullReferenceException( "Clone was not created." ); }
        return clone
    }
}

public abstract class PersonBase<T> : CloneableExBase<T> where T : PersonBase<T> {
    public string Name { get; set; }

    protected override void FillClone( T clone ) {
        clone.Name = this.Name;
    }
}

public sealed class Person : PersonBase<Person> {
    protected override Person CreateClone() { return new Person(); }
}

public abstract class EmployeeBase<T> : PersonBase<T> where T : EmployeeBase<T> {
    public string Department { get; set; }

    protected override void FillClone( T clone ) {
        base.FillClone( clone );
        clone.Department = this.Department;
    }
}

public sealed class Employee : EmployeeBase<Employee> {
    protected override Employee CreateClone() { return new Employee(); }
}

这是很容易写接口自己如果你需要它:

public interface ICloneable<T> : ICloneable
        where T : ICloneable<T>
{
    new T Clone();
}

具有读最近的文章 为什么复制的对象是一个可怕的事情吗?, 我认为这个问题需要额外的clafirication.其他的答案在这里,提供良好的建议,但还是答案是不完整的-为什么没有 ICloneable<T>?

  1. 使用

    所以,你有一个类实现它。同时以前你有一种想 ICloneable, 它现在已经被一般接受 ICloneable<T>.你会需要编辑。

    然后,你可以有一种方法,检查,如果一个物体 is ICloneable.现在怎么办?你不能这样做 is ICloneable<> 和如你所不知道的对象的类型在编译类型,你不能做的方法通用的。第一次真正的问题。

    所以你需要有两个 ICloneable<T>ICloneable, 前实现后者。这样一个实施者将需要实施这两种方法- object Clone()T Clone().不,谢谢,我们已经有足够的乐趣 IEnumerable.

    正如已经指出的那样,还有的复杂性继承。虽然协方可能看起来解决这个问题,一个源类型需要实现 ICloneable<T> 它自己类型,但已经有一个方法,用同样的签名(=参数,基本上)-对 Clone() 基类。制作你的新克隆方法的界面明确毫无意义,你将失去优势寻求当时创造的 ICloneable<T>.因此添加的 new 关键词。但是不要忘了你也需要复盖基类的 Clone() (的执行情况具有保持均匀的所有源类别,即返回的相同目的从每个克隆方法,所以基的克隆方法是 virtual)!但是,不幸的是,你不能两个 overridenew 方法,用同样的签名。选择第一个关键词,你会失去了目标,你想有时候添加 ICloneable<T>.Chossing的第二个,你会打破口本身,使得方法,应做同样的回报不同的对象。

  2. 你想要的 ICloneable<T> 为了舒适,但是舒适不是什么接口的设计,他们的意思是(一般面向对象)统一行为的对象(虽然在C#中,它仅限于统一外行为,例如方法和性质,不是他们的工作).

    如果第一种原因不相信你呢,你可以的对象 ICloneable<T> 也可能作限制性地限制的类型返回的克隆的方法。不过,讨厌的程序员可以实现 ICloneable<T> 在T类型不是,是执行它。因此,要实现你的限制,可以添加一个不错的约束的通用参数:
    public interface ICloneable<T> : ICloneable where T : ICloneable<T>
    肯定更具限制性的,一个没有 where, 你不可能仍然限制, T 是的类型,这是实现接口(你可以从 ICloneable<T> 不同类型的实现的话)。

    你看,即使这一目的不可能实现(原 ICloneable 也失败在此,没有接口可以真正地限制行为实施类)。

正如你可以看到,这证明了使用通用的接口是难以充分执行,并且也真的不需要的和毫无用处的。

但是,回到这个问题,什么您真正追求的是具有舒适当的克隆的一个对象。有两种方式来做到这一点:

另外的方法

public class Base : ICloneable
{
    public Base Clone()
    {
        return this.CloneImpl() as Base;
    }

    object ICloneable.Clone()
    {
        return this.CloneImpl();
    }

    protected virtual object CloneImpl()
    {
        return new Base();
    }
}

public class Derived : Base
{
    public new Derived Clone()
    {
        return this.CloneImpl() as Derived;
    }

    protected override object CloneImpl()
    {
        return new Derived();
    }
}

这一解决方案提供了舒适和预期的行为于用户使用,但这也太长时间来实施。如果我们不希望有的"舒服"的方法返回的流类型中,这是更容易的只有 public virtual object Clone().

因此,让我们看到的"最终"的解决方案-什么C#是真的intented给我们的安慰?

扩展的方法!

public class Base : ICloneable
{
    public virtual object Clone()
    {
        return new Base();
    }
}

public class Derived : Base
{
    public override object Clone()
    {
        return new Derived();
    }
}

public static T Copy<T>(this T obj) where T : class, ICloneable
{
    return obj.Clone() as T;
}

它的名字命名 复制 不要碰撞的电流 克隆 方法(compiler喜欢的类型自己的宣布方法在扩展部分)。的 class 约束是有的速度(不需要空检查等)。

我希望这个澄清为什么不要做 ICloneable<T>.然而,它建议不要实施 ICloneable 在所有。

虽然这个问题是很老(5年后写这个答案:),并已经回答了,但我发现这篇文章回答了这个问题非常好,检查它的此处

修改

下面是从回答问题的文章引用(请务必阅读完整的文章,它包含其他有趣的东西):

  

有在互联网上指向2003年的博客文章多次提到   由布拉德·艾布拉姆斯 - 在微软所采用的时间 - 在一些   讨论有关ICloneable想法。博客条目,可以发现   地址为:实施ICloneable 。尽管误导   标题,这篇博客调用不执行ICloneable,主要   因为浅/深混乱。第二条在一条直线结束   建议:如果你需要一个克隆机制,定义自己的克隆,或   复制的方法,并确保您清晰记录无论是   深或浅拷贝。一个适当的模式是:public <type> Copy();

一个大问题是,它们不能限制吨至是相同的类。富勒例如什么会阻止你这样做:

interface IClonable<T>
{
    T Clone();
}

class Dog : IClonable<JackRabbit>
{
    //not what you would expect, but possible
    JackRabbit Clone()
    {
        return new JackRabbit();
    }

}

他们需要的参数限制,如:

interfact IClonable<T> where T : implementing_type

这是一个很好的问题...你可以做你自己的,但:

interface ICloneable<T> : ICloneable
{
  new T Clone ( );
}

安德烈说,它被认为是一个坏的API,但我还没有听说过这个界面变得过时东西。这将打破万吨接口... 克隆方法应该进行浅拷贝。 如果该对象还提供深层副本,一个重载克隆(布尔深)都可以使用。

编辑:模式I使用“克隆”的对象,正在通过一个原型在构造

class C
{
  public C ( C prototype )
  {
    ...
  }
}

这消除了任何潜在的冗余代码执行的情况。 顺便说一句,谈论ICloneable的限制,是不是真的到对象本身来决定是否一个浅克隆或深克隆,甚至部分浅/深部分克隆,应该执行?如果我们真正关心的,只要对象的作品如预期?在某些情况下,良好的克隆实施很可能会包括浅层和深层克隆两者。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top