cloning an object in C#
I want to clone an object with using the ICloneable
interface
and for some reason I can't clone in my program. Here is my code:
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;
}
}
Inside another class when I am trying to use the Clone()
method, for some reason the compiler can't find the method. Here is my other method that is trying to Clone:
public InfoLaye开发者_开发技巧r(string LayerName,List<GeoInfo> oldGeoInfos)
{
this.LayerName = LayerName;
this.GeoInfos = new List<GeoInfo>();
oldGeoInfos.ForEach((item) =>
{
GeoInfos.Add((GeoInfo)((ICloneable)item.Clone()));
});
}
The parentheses around your cast are not correct. It should read
GeoInfos.Add((GeoInfo)((ICloneable)item).Clone());
(By the way: Why the .ForEach() ?
this.GeoInfos = oldGeoInfos.Select(item => ((GeoInfo)((ICloneable)item.Clone()))).ToList();
does the job as well.)
As others have said you have implemented the interface explicitly.What I do is create another method that returns a typesafe version of the clone method so I tend to include.
public GeoInfo Clone()
{
return new GeoInfo(InfoID, InfoName, InfoLocation, Description, InfoType);
}
and change the explicity implemented clone method to be (the public modifier should be removed)...
object ICloneable.Clone()
{
return Clone(); //will call the public method as above
}
This way you don't have to cast from an object to the real type.
However there are a number of difficulties with ICloneable:
- You don't know if the clone should be a deep or shallow clone
- You have to provide a mechanism for derived classes to clone itself which you can attempt to do via virtual methods. I tend to seal my classes in cases I cannot ensure proper cloning in derived types but that is a decision to be made based around your architcture and needs.
You should only call your method
public object Clone()
Edit:
Or call your method
oldGeoInfos.ForEach((item) =>
{
GeoInfos.Add((GeoInfo)(((ICloneable)item).Clone()));
});
note extra ()
.
The line must read
GeoInfos.Add((GeoInfo)((ICloneable)item).Clone());
But consider in your GeoInfo
class to not use explicit interface implementation (your example shouldn't compile anyway), so that it reads:
public object Clone()
{
//...
}
Then you can simply do
GeoInfos.Add((GeoInfo)item.Clone());
You have implemented ICloneable.Clone
explicitly, which requires that the object is cast to ICloneable
before the method cane be called.
See Explicit Interface Implementation on MSDN.
If you want the method callable on your object, change the method declaration to:
public object Clone()
Alternatively, if you want to keep static type checking, leave your current implementation as-is, and add the following:
public GeoInfo Clone()
{
return ((ICloneable)this).Clone();
}
精彩评论