编程语言
首页 > 编程语言> > c# – 如何创建列表集的深层副本

c# – 如何创建列表集的深层副本

作者:互联网

假设我有以下课程:

public class Author
{
    public int ID {get; private set;}
    public string firstName {get; private set;}
    public string lastName {get; private set; }

    public Author(int id, string firstname, string lastname)
    {
        this.ID = ID;
        this.firstName = firstname;
        this.lastName = lastName;
    }

    public static Author Clone(Author clone)
    {
        Author copyAuth = new Author(clone.ID, clone.firstName, clone.lastName);
        return copyAuth;
    }
}

public class Book
{
    public string bookTitle {get; private set;}
    private List<Author> authors;
    private List<Author> copyofAuthors;
    public string ISBN {get; private set; }

    public Book(string bookTitle, List<Author> authors, string ISBN)
    {
        copyofAuthors = new List<Author>();
        this.bookTitle = bookTitle;
        this.ISBN = ISBN;
        //How do I create a deep copy of my authors List?

        foreach(Author copy in authors)
        {
            Author addAuthors = Author.Clone(copy);
            copyofAuthors.Add(addAuthors);
        }
    }
}

如何创建List< Authors>的深层副本?采集?我已经阅读了StackOverFlow上有关建议序列化的其他页面,以及我不熟悉并且看起来令人困惑的建议.

我按照this link创建了我的克隆方法.

问题1:

以上实施是否被视为深层复制?如果是这样,可以这样做吗?我的意思是,构造函数中的foreach循环将作者复制到新的列表集合.

问题2:

如果我修改了copyofAuthor集合中的任何内容,它就不再引用原始集合了吗?那么原始系列应该保持不变?

更新#1:

    public List<Author> Authors
    {
        get
        {
            return returnAuthors(authors);
        }

    }

    private List<Author> returnAuthors(List<Author> copyList)
    {
        List<Author> getAuthors = new List<Author>();

        foreach(Author copy in copyList){
            getAuthors.Add(Author.Clone(copy));
        }

        return getAuthors;
    }

我是否正确实现了我的getter集合,以便在返回List集合时,它独立于原始集合?因此,从getter返回的集合所做的任何更改都不会反映在原始集合中吗?

更新#2:

使用ReadOnlyCollection

    public class Book
    {

        public string bookTitle {get; private set;}
        private ReadOnlyCollection<Author> authors;
        public string ISBN {get; private set; }


        public Book(string bookTitle, ReadOnlyCollection<Author> authors, string ISBN)
        {

            this.bookTitle = bookTitle;
            this.ISBN = ISBN;
            //Is it okay to do this? 
            this.authors = authors;

        }

        public List<Author> Authors
        {
            get
            {   //Create a shallow copy
                return new ReadOnlyCollection<Author>(authors);
            }

        }

    }

解决方法:

在评论中对此进行排序太难了.

>从Author类中删除Clone方法.这没用.

在你的书课上,你有两个问题需要解决.

>构造函数采用作者列表,但传递它的调用者可能会更改它.如果我们只是复制引用,那么调用者可能会意外地更改该书所持有的列表.
>这本书给出了一份作者名单.如果呼叫者再次向该列表添加内容,他们就会改变这本书.

您可以使用不可变集合解决这两个问题.如果您还没有使用NuGet,请下载不可变集合库.

using System.Collections.Immutable;
...
public class Book
{
  public string bookTitle {get; private set;}
  private ImmutableList<Author> authors;
  public IReadOnlyList<Author> Authors { get { return authors; } }
  public string ISBN {get; private set; }

  public Book(string bookTitle, IEnumerable<Author> authors, string ISBN)
  {
    this.authors = ImmutableList<Author>.Empty.AddRange(authors);
    this.bookTitle = bookTitle;
    this.ISBN = ISBN;
  }
}

那里.现在你复制了作者序列,所以如果调用者改变了那个序列,不用担心,你就有了副本.然后你分发一个由不可变集合实现的IReadOnlyList,所以没有人可以改变它.

结合更多的事情.你问“这是对的吗?”

public class Book
{
    private ReadOnlyCollection<Author> authors;
    public Book(ReadOnlyCollection<Author> authors)
    {
        //Is it okay to do this? 
        this.authors = authors;
    }

    public List<Author> Authors
    {
        get
        {   //Create a shallow copy
            return new ReadOnlyCollection<Author>(authors);
        }
    }

(删除了多余的东西).

不,这是不对的,原因有两个.首先,只读集合只是一个可变集合的包装器.您仍然处于调用者控制底层集合的情况,因此可以更改它.

其次,打字不太合适;你不能将ReadOnlyCollection转换为List.

我知道这令人困惑.这里有一个微妙的区别.只读集合就是:您只能阅读它.这并不意味着别人不能写出来!这样的集合仍然是可变的,它不是你可变的.不可变的集合是真正不可改变的;没人能改变它.

下一篇:通过使作者和书籍都不可变,你做得很好.但是,如果你想改变呢?如您所知,更改不可变书籍意味着制作新书.但是你已经有了一本旧书;你怎么能有效地做到这一点?常见的模式是:

public class Book
{
  public string Title {get; private set;}
  private ImmutableList<Author> authors;
  public IReadOnlyList<Author> Authors { get { return authors; } }
  public string ISBN {get; private set; }

  public Book(string title, IEnumerable<Author> authors, string ISBN) : this(
    title, 
    ImmutableList<Author>.Empty.AddRange(authors),
    ISBN) {}

  public Book(string title, ImmutableList<Authors> authors, string ISBN) 
  {
    this.Title = title;
    this.Authors = authors;
    this.ISBN = ISBN;
  }
  public Book WithTitle(string newTitle)
  {
    return new Book(newTitle, authors, ISBN); 
  }
  public Book WithISBN(string newISBN)
  {
    return new Book(Title, authors, newISBN);
  }
  public Book WithAuthor(Author author)
  {
    return new Book(Title, authors.Add(author), ISBN);
  }
  public static readonly Empty = new Book("", ImmutableList<Author>.Empty, "");
}

现在你可以这样做:

Book tlotr = Book.Empty.WithAuthor("JRRT").WithTitle("The Lord Of The Rings");

等等.

标签:c,deep-copy,shallow-copy
来源: https://codeday.me/bug/20190608/1201137.html