2010-11-07 2 views
4

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

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())); 
     }); 
    } 
+0

Sidenote: Вы можете подумать о том, чтобы сделать «GeoInfos» неизменным, тогда клонирование становится ненужным. Но, конечно, я не знаю, возможно ли это или разумно в этом конкретном случае. – CodesInChaos

ответ

5

Скобки вокруг вашего приведения неверны. Он должен читать

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

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

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

делает работу, а)

1

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

public object Clone() 

Edit:
Или позвоните ваш метод

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

примечание экстра ().

0

Линия должна читать

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

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

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

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

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

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

См. Explicit Interface Implementation на MSDN.

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

public object Clone() 

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

public GeoInfo Clone() 
{ 
    return ((ICloneable)this).Clone(); 
} 
3

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

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

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

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

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

Однако существует ряд трудностей, с ICloneable:

  • Вы не знаете, если клон должен быть deep or shallow clone
  • Вы должны обеспечить механизм для производных классов, чтобы клонировать себя, который вы можете попытаться сделать с помощью виртуальных методов. Я склонен запечатывать свои классы в случаях, когда я не могу обеспечить правильное клонирование в производных типах, но это решение, которое нужно сделать, основываясь на вашей архитектуре и потребностях.
Смежные вопросы