клонирование объекта в C # - PullRequest
4 голосов
/ 07 ноября 2010

Я хочу клонировать объект с помощью интерфейса ICloneable и по какой-то причине не могу клонировать в моей программе.Вот мой код:

public class GeoInfo : ICloneable
{
    private long InfoID;
    private string InfoName;
    private Location InfoLocation;
    private string Description;
    private InfoTypes InfoType;
    public GeoInfo(long InfoID)
    {

        this.InfoID = InfoID;
    }
    public GeoInfo(long InfoID, Location InfoLocation):this(InfoID)
    {
        this.InfoLocation = InfoLocation;
    }
    public GeoInfo(long InfoID, string InfoName, Location InfoLocation, string Description, InfoTypes InfoType):this(InfoID,InfoLocation)
    {
        this.InfoName = InfoName;
        this.Description = Description;
        this.InfoType = InfoType;
    }
    public object ICloneable.Clone()
    {
        GeoInfo toReturn = new GeoInfo(InfoID, InfoName, InfoLocation, Description, InfoType);
        return (object)toReturn;
    }

}

Внутри другого класса, когда я пытаюсь использовать метод Clone(), по какой-то причине компилятор не может найти метод.Вот мой другой метод, который пытается клонировать:

public InfoLayer(string LayerName,List<GeoInfo> oldGeoInfos)
    {
        this.LayerName = LayerName;
        this.GeoInfos = new List<GeoInfo>();
        oldGeoInfos.ForEach((item) =>
        {
            GeoInfos.Add((GeoInfo)((ICloneable)item.Clone()));
        });
    }

Ответы [ 5 ]

5 голосов
/ 07 ноября 2010

Скобки вокруг вашего состава неверны.На нем должно быть написано

GeoInfos.Add((GeoInfo)((ICloneable)item).Clone());

(Кстати: почему .ForEach ()?

this.GeoInfos = oldGeoInfos.Select(item => ((GeoInfo)((ICloneable)item.Clone()))).ToList();

тоже делает свою работу.)

3 голосов
/ 08 ноября 2010

Как уже говорили другие, вы в явном виде реализовали интерфейс. Что я делаю, так это создаю другой метод, который возвращает типизированную версию метода клона, поэтому я стараюсь включать.

public GeoInfo Clone()
{
    return new GeoInfo(InfoID, InfoName, InfoLocation, Description, InfoType);
}

и изменить реализованную простотуклонируемый метод (публичный модификатор должен быть удален) ...

object ICloneable.Clone()
{
    return Clone();  //will call the public method as above
}

Таким образом, вам не нужно приводить объект к реальному типу.

Однако естьряд трудностей с ICloneable:

  • Вы не знаете, должен ли клон быть глубоким или неглубоким клоном
  • Вы должны предоставить механизм дляпроизводные классы для клонирования себя, что вы можете попытаться сделать с помощью виртуальных методов.Я склонен запечатывать свои занятия в тех случаях, когда я не могу обеспечить надлежащее клонирование в производных типах, но это решение должно приниматься исходя из вашей архитектуры и потребностей.
1 голос
/ 07 ноября 2010

Вы должны вызывать только свой метод

public object Clone()

Редактировать:
Или вызывать свой метод

oldGeoInfos.ForEach((item) =>
{
    GeoInfos.Add((GeoInfo)(((ICloneable)item).Clone()));
});

note extra ().

0 голосов
/ 07 ноября 2010

Вы ввели ICloneable.Clone явно, что требует, чтобы объект был приведен к ICloneable до вызова метода.

См. Явная реализация интерфейса в MSDN.

Если вы хотите, чтобы метод вызывался в вашем объекте, измените объявление метода на:

public object Clone()

В качестве альтернативы, если вы хотите сохранить статическую проверку типов, оставьте текущую реализацию как есть и добавьте следующее:

public GeoInfo Clone()
{
    return ((ICloneable)this).Clone();
}
0 голосов
/ 07 ноября 2010

Строка должна иметь вид

GeoInfos.Add((GeoInfo)((ICloneable)item).Clone());

Но учтите, что в вашем классе GeoInfo не следует использовать явную реализацию интерфейса (ваш пример не должен компилироваться в любом случае), поэтому она читает:

public object Clone()
{
    //...
}

Тогда вы можете просто сделать

GeoInfos.Add((GeoInfo)item.Clone());
...