在评论中解决这个问题变得太难了。
- 从您的 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;
}
}
那里。现在你做一个copy of the sequence作者,所以如果调用者更改了该顺序,不用担心,您有一个副本。并且您分发一个由不可变集合实现的 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);
}
}
(去除多余的东西)。
不,这并不完全正确,有几个原因。首先,只读集合只是一个wrapper围绕可变集合。您仍然处于调用者控制底层集合的情况,因此可以更改它。
其次,打字不太好;您无法将 ReadOnlyCollection 转换为 List。
我知道这很令人困惑。这里有一个微妙的区别。只读集合就是:you只能读它。这并不意味着其他人写不出来!这样的合集还是mutable,它只是不可变的by you。不可变集合确实是不可变的;没有人可以改变它。
接下来:通过使作者和书都是不可变的,你做得很好。但如果你想改变它怎么办?正如您所注意到的,更改一本不可变的书意味着制作一本新书。但你已经有一本旧书了;你怎样才能有效地做到这一点?常见的模式是:
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");
等等。