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の汎用パラメーターは何でもかまいませんので、必要な型の汎用引数が必要です。ABC

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;
}

欠点は、継承された型ではなく、クローンがオブジェクトを返すことです。しかし、それはフレームワーク自体で広く使用されているアプローチです。

于 2013-04-04T09:39:16.773 に答える