我想用CloneInstance方法创建接口,该方法返回该实例的通用类。例如:

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>。有什么办法可以做到这一点?

最佳答案

您可以为将实现T的具体类接受通用的ICloneableExtended参数:

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是为了清楚起见,但是如果您由于世界范围内的随机使用而不想使用它,那么只需选择自己的等效非通用接口即可)。

关于c# - 通用CloneInstance,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33754866/

10-09 10:08