Blu*_*nce 210 .net c# icloneable
是否存在通用ICloneable<T>不存在的特殊原因?
如果我不想在每次克隆东西时都需要施放它,那会更舒服.
Mar*_*ell 136
除了安德烈的答复(我同意,+1) -当ICloneable 是做了,你也可以选择明确的实施,使公众Clone()返回一个类型的对象:
public Foo Clone() { /* your code */ }
object ICloneable.Clone() {return Clone();}
Run Code Online (Sandbox Code Playgroud)
当然,第二个问题是泛型ICloneable<T>继承.
如果我有:
public class Foo {}
public class Bar : Foo {}
Run Code Online (Sandbox Code Playgroud)
我实施了ICloneable<T>,然后实施了ICloneable<Foo>吗?ICloneable<Bar>?你很快就开始实现了很多相同的接口......与演员相比......真的很糟糕吗?
And*_*kin 107
ICloneable现在被认为是一个糟糕的API,因为它没有指定结果是深拷贝还是浅拷贝.我认为这就是为什么他们不改进这个界面.
您可以执行类型化克隆扩展方法,但我认为它需要不同的名称,因为扩展方法的优先级低于原始方法.
Dav*_*ean 19
我需要问一下,除了实现它之外,你究竟会对接口做些什么呢?接口通常仅在您转换为它时才有用(即此类支持'IBar'),或者具有接受它的参数或设置器(即我采用'IBar').使用ICloneable - 我们经历了整个框架,并且未能在任何地方找到一个不同于其实现的单一用法.我们也未能在"现实世界"中找到任何除了实现它之外的其他用法(在我们有权访问的~60,000个应用程序中).
现在,如果您只想强制执行一个您希望"可复制"对象实现的模式,那么这是一个非常好的用法 - 并继续.您还可以确定"克隆"对您意味着什么(即深或浅).但是,在这种情况下,我们(BCL)不需要定义它.当需要交换类型为不相关库之间的抽象的实例时,我们只在BCL中定义抽象.
大卫基恩(BCL队)
TcK*_*cKs 12
我认为"为什么"这个问题是不必要的.有很多接口/类/等...这非常有用,但不是.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(); }
}
Run Code Online (Sandbox Code Playgroud)
Mau*_*fer 10
这是很容易写自己的界面,如果你需要它:
public interface ICloneable<T> : ICloneable
where T : ICloneable<T>
{
new T Clone();
}
Run Code Online (Sandbox Code Playgroud)
最近阅读了文章为什么要复制一个对象是一件可怕的事情?,我认为这个问题需要额外的肯定.这里的其他答案提供了很好的建议,但答案仍然不完整 - 为什么不ICloneable<T>呢?
用法
所以,你有一个实现它的类.虽然以前你有一个想要的方法ICloneable,但它现在必须是通用的才能接受ICloneable<T>.你需要编辑它.
然后,你可能有一个方法来检查一个对象is ICloneable.现在怎么办?你不能这样做is ICloneable<>,因为你不知道在compile-type中对象的类型,你不能使该方法通用.第一个真实问题.
所以,你需要同时拥有ICloneable<T>和ICloneable,前者实现了后者.因此,实施者需要实现这两种方法 - object Clone()和T Clone().不,谢谢,我们已经有了足够的乐趣IEnumerable.
正如已经指出的那样,继承的复杂性也很大.虽然协方差似乎可以解决这个问题,但派生类型需要实现ICloneable<T>自己的类型,但是已经有一个方法具有相同的签名(基本上是=参数) - Clone()基类的方法.使您的新克隆方法界面显式无意义,您将失去创建时所寻求的优势ICloneable<T>.所以添加new关键字.但是不要忘记你还需要覆盖基类' Clone()(对于所有派生类,实现必须保持一致,即从每个克隆方法返回相同的对象,因此必须使用基本克隆方法virtual)!但是,遗憾的是,你不能同时使用相同的签名override和new方法.选择第一个关键字,您将失去添加时想要的目标ICloneable<T>.选择第二个,你将破坏界面本身,使得应该做同样的方法返回不同的对象.
点
你想要ICloneable<T>舒适,但舒适不是界面的设计,它们的意义是(通常是OOP)来统一对象的行为(尽管在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();
}
}
Run Code Online (Sandbox Code Playgroud)
该解决方案为用户提供了舒适性和预期的行为,但实施起来也太长了.如果我们不想让"舒适"方法返回当前类型,那么就更容易拥有public virtual object Clone().
那么让我们看看"终极"解决方案 - C#中真正意图给予我们安慰的是什么?
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;
}
Run Code Online (Sandbox Code Playgroud)
它被命名为Copy,不与当前的Clone方法冲突(编译器更喜欢类型自己声明的方法而不是扩展方法).该class约束是有速度(不需要空检查等).
我希望这澄清了为什么不这样做的原因ICloneable<T>.但是,建议不要实施ICloneable.
| 归档时间: |
|
| 查看次数: |
43565 次 |
| 最近记录: |