Как клонировать общий список экземпляров класса, производного от абстрактного класса в C #? - PullRequest
0 голосов
/ 08 сентября 2011

У меня есть базовый класс: abstract class Base и некоторые производные классы: class Derived: Base, что все члены данных находятся в базовом классе. У меня есть еще один общий список: List<Base> list. Теперь я хочу выполнить операцию Clone() в списке. Я прочитал эту ветку , но обнаружил, что моя ситуация немного сложнее. Поскольку базовый класс является абстрактным, элементы списка нельзя клонировать с помощью конструктора копирования или реализации интерфейса ICloneable. Но так как все члены данных находятся в базовом классе, будет избыточно писать один и тот же кусок кода для клонирования в производных классах снова и снова. Каков наилучший способ сделать эту работу? Спасибо за подсказки.

Обновление: прикрепленный упрощенный исходный код

public class Point : ICloneable
{
    public int X { get; set; }
    public int Y { get; set; }

    public Point(int x, int y)
    { X = x; Y = y; }

    public Point(Point p)
    {
        X = p.X; Y = p.Y;
    }

    public object Clone()
    {
        return MemberwiseClone();
    }
}

public abstract class ObjectThatHasPosition : ICloneable
{
    public Point CurrentPosition { get; set; }
    public ObjectThatHasPosition(Point p)
    { CurrentPosition = new Point(p); }
    public object Clone()
    {
        return MemberwiseClone();
    }
}

public class Man : ObjectThatHasPosition
{
    public Man(Point p) : base(p) { }
}

static class Extensions
{
    public static List<ObjectThatHasPosition> Clone(this List<ObjectThatHasPosition> src)
    {
        List<ObjectThatHasPosition> dst = new List<ObjectThatHasPosition>(src.Count);
        src.ForEach((item) => { dst.Add((ObjectThatHasPosition)item.Clone()); });
        return dst;
    }
}

    static void Main(string[] args)
    {
        List<ObjectThatHasPosition> firstList = new List<ObjectThatHasPosition>();
        firstList.Add(new Man(new Point(0, 0)));
        List<ObjectThatHasPosition> anotherList = firstList.Clone();
        firstList[0].CurrentPosition.X = 1;
    }

Видно, что оба списка одинаковы.

1 Ответ

4 голосов
/ 08 сентября 2011

Я не понимаю, почему Base не может реализовать ICloneable:

public abstract class Base : ICloneable
{
    public object Clone()
    {
        return MemberwiseClone();
    }
}

Это все равно вернет правильный экземпляр (то есть тот же тип, что и существующий объект) при вызове напроизводный класс.Любые поля в производных классах также будут скопированы, хотя и поверхностно.В качестве конкретного примера:

using System;

public abstract class BaseClass : ICloneable
{
    public object Clone()
    {
        return MemberwiseClone();
    }
}

public class Derived : BaseClass
{
    private readonly string name;

    public Derived(string name)
    {
        this.name = name;
    }

    public override string ToString()
    {
        return "Derived with name " + name;
    }
}

class Test
{
    static void Main(string[] args)
    {
        BaseClass b = new Derived("fred");

        object clone = b.Clone();
        Console.WriteLine(clone.ToString());
    }
}

РЕДАКТИРОВАТЬ: Я подозреваю вы хотите что-то вроде:

public abstract class ObjectThatHasPosition : ICloneable
{
    public Point CurrentPosition { get; set; }
    public ObjectThatHasPosition(Point p)
    {
        CurrentPosition = p; 
    }

    public object Clone()
    {
        var clone = (ObjectThatHasPosition) MemberwiseClone();
        clone.CurrentPosition = (Point) CurrentPosition.Clone();
    }
}
...