在 C# 中使用 ICloneable 接口进行深度复制的问题

Problem with making a deepcopy using IClonable interface in C#

我在制作对象的深拷贝时遇到问题。

我需要深拷贝 Graph class 对象。 这是我的 Graph class 和 Edge class,Graph 从中使用对象。

class Graph : ICloneable
    {
        private List<Edge> edges;
        private List<int> vertices;

        public Graph()
        {
            edges = new List<Edge>();
            vertices = new List<int>();
        }
       
        public List<Edge> Edges
        {
            get
            {
                return edges;
            }
        }

        public List<int> Vertices
        {
            get
            {
                return vertices;
            }
        }
    }

    class Edge
    {
        public int vertexV;
        public int vertexU;
        public int weigth;

        public Edge(int vertexV, int vertexU, int weigth)
        {
            this.vertexV = vertexV;
            this.vertexU = vertexU;
            this.weigth = weigth;
        }
    }

到目前为止,我已经尝试过:

 public Graph Clone() { return new Graph(this); }
 object ICloneable.Clone()
 {
       return Clone();
 }
public Graph(Graph other)
{
    this.edges = other.edges;
    this.vertices = other.vertices;
}
public object Clone()
{
     var clone = (Graph)this.MemberwiseClone();
     return clone;
}

但它只创建了一个浅表副本,无法解决问题。当然,IClonable 接口已为上述所有示例实现。我尝试在网上查看其他示例,但没有结果。我正在使用 foreach 循环添加来自 edgesvertices 的所有元素,但该解决方案非常慢。

欢迎体验 OOP 的乐趣!

开个玩笑,在构造克隆时,您需要创建新的 List 对象:

public Graph(Graph other)
{
    this.edges = new List<int>(other.edges);
    this.vertices = new List<int>(other.vertices);
}

您的 Clone 代码将保持不变:

public Graph Clone() { 
    return new Graph(this); 
}

object ICloneable.Clone()
{
    return Clone();
}

如果您的 Edge class 是可变的,那么您也需要克隆它们:

public Graph(Graph other)
{
    this.edges = other.edges.Select(e => new Edge(e.vertexV, e.vertexU, e.weight)).ToList();
    this.vertices = new List<int>(other.vertices);
}

由于您的节点是 int,这是一种值类型,您可以考虑制作 Graph class immutable。不可变类型永远不需要克隆,这可以使代码更容易理解。

这应该有效

public object Clone()
{
    Graph graph = new Graph();
    edges.ForEach(e => graph.edges.Add(new Edge(e.vertexV, e.vertexU, e.weigth)));
    graph.vertices.AddRange(vertices.ToArray());
    return graph;
}