在C#中克隆一个对象

时间:2010-11-07 20:43:55

标签: c# icloneable

我想使用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 个答案:

答案 0 :(得分:5)

你的演员周围的括号不正确。它应该读

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

(顺便说一句:为什么.ForEach()?

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

也可以完成这项工作。)

答案 1 :(得分:3)

正如其他人所说,你已经明确地实现了接口。我所做的是创建另一个返回clone方法的类型安全版本的方法,所以我倾向于包含。

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
  • 您必须为派生类提供克隆自身的机制,您可以尝试通过虚拟方法执行此操作。如果我无法确保派生类型中的正确克隆,我倾向于密封我的课程,但这是根据您的结构和需求做出的决定。

答案 2 :(得分:1)

你应该只调用你的方法

public object Clone()

修改
或者致电您的方法

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

注意额外()

答案 3 :(得分:0)

该行必须阅读

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

但是在你的GeoInfo类中考虑不使用显式接口实现(你的例子不应该编译),所以它读作:

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

然后你可以简单地做

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

答案 4 :(得分:0)

您已明确实施ICloneable.Clone,这要求在调用方法手杖之前将对象强制转换为ICloneable

请参阅MSDN上的Explicit Interface Implementation

如果要在对象上调用方法,请将方法声明更改为:

public object Clone()

或者,如果要保留静态类型检查,请按原样保留当前实现,并添加以下内容:

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