通用克隆实例
本文关键字:实例 | 更新日期: 2023-09-27 18:22:16
我想要用CloneInstance方法创建接口,该方法返回该实例的Generic类。例如:
public interface ICloneableExtended<T> where T : this
{
T CloneInstance();
}
public class Car : ICloneableExtended
{
...
...
public Car CloneInstance()
{ .. }
}
Foo()
{
Car car ...;
var clonedCar = car.CloneInstance();
}
在类Car
的定义中,我只需要使用ICloneableExtended
,而不需要使用ICloneableExtended<T>
。有办法做到这一点吗?
您可以接受将实现ICloneableExtended
:的具体类的通用T
参数
interface ICloneableExtended<T> {
Clone();
}
class Car : ICloneableExtended<Car> {
public Car Clone() {
throw new NotImplementedException();
}
}
您可以考虑使T
参数协变(如果您希望将ICloneableExtended<Car>
与许多具体类保持在一起-这将实现ICloneableExtended<T>
):
interface ICloneableExtended<out T> {
Clone();
}
请注意,您可能不需要通用的接口,您已经有了ICloneable
(及其所有缺点和误用):
interface ICloneableExtended<out T> : ICloneable {
Clone();
}
对于二进制可序列化类型,您甚至可以实现一个基本的、可重用的(但效率很低)基类:
interface ICloneableExtended<T> : ICloneable {
T Clone();
}
abstract class Cloneable<T> : ICloneableExtended<T> {
public virtual T Clone() {
using (var ms = new MemoryStream()) {
var formatter = new BinaryFormatter();
formatter.Serialize(ms, this);
ms.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(ms);
}
}
object ICloneable.Clone() {
return Clone();
}
}
sealed class Car : Cloneable<Car> { }
使用这种方法,每个具体类都必须实现ICloneableExtended<T>
,但不能重载仅通过返回值进行区分的Clone()
方法,因此最好显式实现ICloneableExtended<T>
。一种不那么令人困惑的方法(对于谁实现这个接口以及谁将使用它)是提供扩展方法:
static class Extensions {
public static T Clone<T>(this object obj) {
var cloneable = obj as ICloneable;
if (cloneable != null)
return (T)cloneable.Clone();
using (var ms = new MemoryStream()) {
return (T)...
}
}
}
(为了清晰起见,我使用ICloneable
,但如果您不想使用它,因为它在全球范围内的随机使用,那么只需选择您自己的等效非通用接口即可)。