【问题标题】:Problem with making a deepcopy using IClonable interface in C#在 C# 中使用 IClonable 接口进行深度复制的问题
【发布时间】:2020-11-14 17:10:23
【问题描述】:

我在制作对象的深层副本时遇到了麻烦。

我需要制作 Graph 类对象的深层副本。 这是我的 Graph 类和 Edge 类,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 的所有元素,但该解决方案非常慢。

【问题讨论】:

标签: c# object cloning icloneable


【解决方案1】:

欢迎享受 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 类是可变的,那么您也需要克隆它们:

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 类设为immutable。永远不需要克隆不可变类型,这可以使代码更容易理解。

【讨论】:

  • 所以我需要在构造函数中创建一个新的Lists,然后克隆方法会是什么样子?
  • 克隆方法会调用原来的构造函数。构造函数负责复制列表。
  • 谢谢!这正是我所需要的。
【解决方案2】:

这应该可以工作

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;
}

【讨论】:

  • 工作方式比我必须使用的双倍 foreach 更快,并且与 NCopy 一样快。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-12-03
  • 2018-10-08
  • 1970-01-01
  • 2011-09-11
  • 1970-01-01
  • 2014-09-05
  • 2015-02-28
相关资源
最近更新 更多