1

我有以下课程(非常简化的版本):

public interface A { }
public abstract class A<TType, TContentType> : A where TType: A
{
    public abstract void Initialise();
    public abstract TType DeepCopy();
    public TContentType Value { get; private set; }
}

public class B : A<B, double>
{
    public override void Initialise() { this.Value = 3.0; }

    public override B DeepCopy() { return new B(); }
}

public class C : A<C, char>
{
    public override void Initialise() { this.Value = 'v'; }

    public override C DeepCopy() { return new C(); }
}

我可以创建一个 A 类型列表,如下所示:

public static List<A> CreateList()
{
    List<A> myList = new List<A>();
    myList.Add(new B());
    myList.Add(new C());
    return myList;
}

我想创建一个方法,给定类型 A 的单个对象,它将根据指定的长度创建这些对象的列表。

例如:

public static List<A> CreateList(A baseA, int length)
{
    List<A> myList = new List<A>();
    for (int i = 0; i < length; i++)
    {
       // create a deep copy of baseA
       // call the Initialise method on the new object
       // add to the list
    }
    return myList;
}

我不确定如何在不知道 A 类型的情况下创建深层副本,因为 A 不包含任何内容.. 我需要为此创建一个通用方法吗?

非常感谢任何指针

4

3 回答 3

1

您使事情变得相当复杂,首先您不需要将泛型参数所属的对象的类型指定为泛型参数 ( TType),因为我们已经拥有该信息。

这是一个解决方案。它有interface IA一个IA Clone()方法。然后我们可以调用该方法并将其安全地转换为Tin CreateList()CreateList需要有一个你想要的类型的泛型参数,因为//A的泛型参数可以是任何东西。BC

public static List<T> CreateList<T>(T baseA, int length) where T : IA
{
    var myList = new List<T>();
    for (int i = 0; i < length; i++)
    {
        myList.Add((T)baseA.Clone());
    }
    return myList;
}

public interface IA
{
    public abstract IA Clone();
}

public abstract class A<TContentType> : IA
{
    public abstract void Initialise();
    public TContentType Value { get; private set; }
}

public class B : A<double>
{
    public override IA Clone()
    {
        var b = new B();
        // transfer properties
        return b;
    }

    //public override void Initialise() { this.Value = 3.0; }
}

public class C : A<char>
{

    public override IA Clone()
    {
        var c = new C();
        // transfer properties
        return c;
    }

    //public override void Initialise() { this.Value = 'v'; }
}
于 2013-04-04T09:51:25.570 回答
1

只是建议如何使您的方法起作用:如果您的参数类型将是A,那么显然A接口必须具有DeepCopy()Initialise()方法。为了让您拥有返回特定类型对象的DeepCopy()方法,您可以使用显式接口实现

public interface A
{
    void Initialise();
    A DeepCopy();
}

public abstract class A<TType, TContentType> : A where TType : A
{
    public abstract void Initialise();
    public abstract TType DeepCopy();
    A A.DeepCopy() { return this.DeepCopy(); }
    public TContentType Value { get; protected set; }
}

public class B : A<B, double>
{
    public override void Initialise() { this.Value = 3.0; }
    public override B DeepCopy() { return new B(); }
}

public class C : A<C, char>
{
    public override void Initialise() { this.Value = 'v'; }
    public override C DeepCopy() { return new C(); }
}

class Program
{
    static void Main(string[] args)
    {
        List<A> listBC = CreateList();
        List<A> list = CreateList(new B(), 3);
    }

    public static List<A> CreateList()
    {
        List<A> myList = new List<A>();
        myList.Add(new B());
        myList.Add(new C());
        return myList;
    }

    public static List<A> CreateList(A baseA, int length)
    {
        List<A> myList = new List<A>(length);

        for (int i = 0; i < length; i++)
        {
            A copy = baseA.DeepCopy();
            copy.Initialise();
            myList.Add(copy);
        }

        return myList;
    }
}

我不知道您的真实代码,但DeepCopy() { return new B(); }必须复制一些成员值对吗?并且在使用副本填充列表时 - 您真的需要初始化它们还是保留深层副本?

于 2013-04-04T09:57:55.293 回答
0

没有内置方法可以创建正确的深层副本。需要深度复制的类型应该实现 IClonable。

您可以从中继承您的 A 接口,然后在 CreateList 中调用 Clone(),将其返回值转换为所需的类型。

public interface A: IClonable { 
    Initialize();
}


public static List<A> CreateList(A baseA, int length)
{
    List<A> myList = new List<A>();
    for (int i = 0; i < length; i++)
    {
       var copy = (A) baseA.Clone();
       copy.initialize();
       myList.Add(copy);
    }
    return myList;
}

缺点是 Clone 返回对象,而不是您继承的类型。但这是框架本身中广泛使用的方法。

于 2013-04-04T09:39:16.773 回答