C# 如何正确地使用集合实现Equals

C# 如何正确地使用集合实现Equals,c#,collections,equals,C#,Collections,Equals,我有下面的类和MSDN记录的2个相等的方法 public class Book { public string bookTitle {get; private set;} public IReadOnlyCollection<Author> authors {get; private set;} public string ISBN {get; private set;} public int numberofpages {get; private set; } public st

我有下面的类和MSDN记录的2个相等的方法

public class Book
{

public string bookTitle {get; private set;}
public IReadOnlyCollection<Author> authors {get; private set;}
public string ISBN {get; private set;}
public int numberofpages {get; private set; }
public string Genre {get; private set; }

public Book(string bookTitle, IReadOnlyCollection<Author> authors, string ISBN, int numberofpages, string genre)
{
    if(string.IsNullOrWhiteSpace(bookTitle)){
        throw new ArgumentNullException("Book Must Have Title!");
    }
    this.bookTitle = bookTitle;

    if(authors.Count < 0){
        throw new ArgumentNullException("You must provide at least one author!");
    }
    this.authors = new ReadOnlyCollection<Author>(new List<Author>(authors));

    if(String.IsNullOrWhiteSpace(ISBN)){
        throw new ArgumentNullException("A Book Has to have an ISBN number. Check online or the back cover");
    }
    this.ISBN = ISBN;
    if(numberofpages <= 0){
        throw new ArgumentNullException("A Book has more than one page!");
    }
    this.numberofpages = numberofpages;
    if(String.IsNullOrWhiteSpace(genre)){
        throw new ArgumentNullException("A Book has a genre. Find it and input it");
    }
    this.Genre = genre;
}


public override bool Equals(Object obj)
{
    if (obj == null)
    {
        return false;
    }

    Book p = obj as Book;
    if ((System.Object)p == null)
    {
        return false;
    }
    return (bookTitle == p.bookTitle) && (authors == p.authors) && (numberofpages == p.numberofpages) && (ISBN == p.ISBN) && (Genre == p.Genre);
}

public bool Equals(Book p)
{
    if ((object)p == null)
    {
        return false;
    }

    return (bookTitle == p.bookTitle) && (authors == p.authors) && (numberofpages == p.numberofpages) && (ISBN == p.ISBN) && (Genre == p.Genre);
}


   public class Author
   {
     public int ID {get; private set;}
     public string firstname {get; private set;}
     public string lastname {get; private set;}

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

     //Rest of code here: just toString method
公共课堂教材
{
公共字符串bookTitle{get;private set;}
公共IReadOnlyCollection作者{get;private set;}
公共字符串ISBN{get;private set;}
public int numberofpages{get;private set;}
公共字符串类型{get;private set;}
公共图书(字符串书名、IReadOnlyCollection作者、字符串ISBN、整数页数、字符串类型)
{
if(string.IsNullOrWhiteSpace(bookTitle)){
抛出新的ArgumentNullException(“书必须有标题!”);
}
this.bookTitle=bookTitle;
如果(authors.Count<0){
抛出新ArgumentNullException(“您必须至少提供一个作者!”);
}
this.authors=新的只读集合(新列表(作者));
if(String.IsNullOrWhiteSpace(ISBN)){
抛出新的ArgumentNullException(“一本书必须有一个ISBN号,请在线或封底查阅”);
}
这是ISBN=ISBN;

如果(numberofpages您的图书类可以/应该实现和。您可能还希望对收藏进行排序。如果没有更多信息,很难推荐一个坚如磐石的答案,但如果您查看我提供的链接/建议,您的项目可能会取得很好的进展。

您必须比较作者列表项。排序和比较是作者在每个索引上的位置,直到它们不相等或您到达列表的末尾。此外,Book和author都应该实现IEquatable以防止问题并保持理智。@MaxSorin-您能告诉我如何实现吗?答案随代码和接口一起提供实现。谢谢,但是,作者并没有这么复杂。它只是一个类使用int author ID、string authorFirstname、string authorLastName。
Authors
只允许我在一条语句中相互比较列表。您可以创建自己的方法来比较
ReadOnlyCollections
中的项目。我更新了我的代码以包含我的Authors类,如果您可以更改代码,请查看,以便我能理解该怎么做。向下滚动它与我在一起。我正在学习,你能告诉我如何创建我自己的方法来比较ReadOnlyCollections中的项目吗?为什么这还不足以让equals方法工作?
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TestArea.Other
{
    public class Author : IComparable<Author>
    {
        public string Name { get; set; }

        public int CompareTo(Author other) => this.Name.CompareTo(other.Name);
    }

    public class Authors :  ReadOnlyCollection<Author>, IEquatable<Authors>
    {
        public Authors(IList<Author> list) : base(list)
        {

        }

        public bool Equals(Authors other)
        {
            //reference equal 
            if (other == this)
            {
                return true;
            }

            //No need to iterate over authors
            if (other == null || other.Count != this.Count)
            {
                return false;
            }

            var thisSorted = this.ToArray();
            var otherSorted = other.ToArray();
            Array.Sort(thisSorted);
            Array.Sort(otherSorted );

            for (int i = 0; i < thisSorted.Length; i++)
            {
                if (thisSorted[i].CompareTo(otherSorted[i]) != 0)
                {
                    return false;
                }
            }

            return true;
        }
    }

    public class Book : IEquatable<Book>
    {

        public string bookTitle { get; private set; }
        public Authors authors { get; private set; }
        public string ISBN { get; private set; }
        public int numberofpages { get; private set; }
        public string Genre { get; private set; }

        //Made Authors parameter as simplified as it could be
        public Book(string bookTitle, IEnumerable<Author> authors, string ISBN, int numberofpages, string genre)
        {
            var authorList = authors.ToList();
            if (string.IsNullOrWhiteSpace(bookTitle))
            {
                throw new ArgumentNullException("Book Must Have Title!");
            }
            this.bookTitle = bookTitle;

            if (authorList.Count() < 0)
            {
                throw new ArgumentNullException("You must provide at least one author!");
            }
            this.authors = new Authors(new List<Author>(authorList));

            if (String.IsNullOrWhiteSpace(ISBN))
            {
                throw new ArgumentNullException("A Book Has to have an ISBN number. Check online or the back cover");
            }
            this.ISBN = ISBN;
            if (numberofpages <= 0)
            {
                throw new ArgumentNullException("A Book has more than one page!");
            }
            this.numberofpages = numberofpages;
            if (String.IsNullOrWhiteSpace(genre))
            {
                throw new ArgumentNullException("A Book has a genre. Find it and input it");
            }
            this.Genre = genre;
        }


        public override bool Equals(Object obj)
        {
            if (obj == null)
            {
                return false;
            }

            Book p = obj as Book;
            if ((System.Object) p == null)
            {
                return false;
            }
            return (bookTitle == p.bookTitle) && (authors.Equals( p.authors)) && (numberofpages == p.numberofpages) &&
                   (ISBN == p.ISBN) && (Genre == p.Genre);
        }

        public bool Equals(Book p)
        {
            if ((object) p == null)
            {
                return false;
            }

            return (bookTitle == p.bookTitle) && (authors.Equals( p.authors)) && (numberofpages == p.numberofpages) &&
                   (ISBN == p.ISBN) && (Genre == p.Genre);
        }
    }

}
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TestArea.Other
{
    public class Author : IComparable<Author>
    {
        public string Name { get; set; }

        public int CompareTo(Author other) => this.Name.CompareTo(other.Name);
    }

    public class Authors :  ReadOnlyCollection<Author>, IEquatable<Authors>
    {
        public Authors(IList<Author> list) : base(list)
        {

        }

        public bool Equals(Authors other)
        {
            //reference equal 
            if (other == this)
            {
                return true;
            }

            //No need to iterate over authors
            if (other == null || other.Count != this.Count)
            {
                return false;
            }

            var thisSorted = this.ToArray();
            var otherSorted = other.ToArray();
            Array.Sort(thisSorted);
            Array.Sort(otherSorted );

            for (int i = 0; i < thisSorted.Length; i++)
            {
                if (thisSorted[i].CompareTo(otherSorted[i]) != 0)
                {
                    return false;
                }
            }

            return true;
        }
    }

    public class Book : IEquatable<Book>
    {

        public string bookTitle { get; private set; }
        public Authors authors { get; private set; }
        public string ISBN { get; private set; }
        public int numberofpages { get; private set; }
        public string Genre { get; private set; }

        //Made Authors parameter as simplified as it could be
        public Book(string bookTitle, IEnumerable<Author> authors, string ISBN, int numberofpages, string genre)
        {
            var authorList = authors.ToList();
            if (string.IsNullOrWhiteSpace(bookTitle))
            {
                throw new ArgumentNullException("Book Must Have Title!");
            }
            this.bookTitle = bookTitle;

            if (authorList.Count() < 0)
            {
                throw new ArgumentNullException("You must provide at least one author!");
            }
            this.authors = new Authors(new List<Author>(authorList));

            if (String.IsNullOrWhiteSpace(ISBN))
            {
                throw new ArgumentNullException("A Book Has to have an ISBN number. Check online or the back cover");
            }
            this.ISBN = ISBN;
            if (numberofpages <= 0)
            {
                throw new ArgumentNullException("A Book has more than one page!");
            }
            this.numberofpages = numberofpages;
            if (String.IsNullOrWhiteSpace(genre))
            {
                throw new ArgumentNullException("A Book has a genre. Find it and input it");
            }
            this.Genre = genre;
        }


        public override bool Equals(Object obj)
        {
            if (obj == null)
            {
                return false;
            }

            Book p = obj as Book;
            if ((System.Object) p == null)
            {
                return false;
            }
            return (bookTitle == p.bookTitle) && (authors.Equals( p.authors)) && (numberofpages == p.numberofpages) &&
                   (ISBN == p.ISBN) && (Genre == p.Genre);
        }

        public bool Equals(Book p)
        {
            if ((object) p == null)
            {
                return false;
            }

            return (bookTitle == p.bookTitle) && (authors.Equals( p.authors)) && (numberofpages == p.numberofpages) &&
                   (ISBN == p.ISBN) && (Genre == p.Genre);
        }
    }

}
 public static class IEnumerableExtensions
    {
        public static bool EqualTo<T>(this IEnumerable<T> enumerable, IEnumerable<T> other)
        {
            //reference equal 
            if (other == enumerable)
            {
                return true;
            }

            if (other == null)
            {
                return false;
            }

            var enumerableSorted = enumerable.ToArray();
            var otherSorted = other.ToArray();

            //No need to iterate over items if lengths are not equal
            if (otherSorted.Length != enumerableSorted.Length)
            {
                return false;
            }

            Array.Sort(enumerableSorted);
            Array.Sort(otherSorted);

            return !enumerableSorted.Where((t, i) => t.Equals(otherSorted[i])).Any();
        }
    }
public override bool Equals(Object obj)
{
    if (obj == null)
    {
        return false;
    }

    Book otherBook = obj as Book;
    if ((System.Object) otherBook == null)
    {
        return false;
    }

    return (bookTitle == otherBook.bookTitle) && 
        otherBook.authors.EqualTo(this.authors) && 
        (numberofpages == otherBook.numberofpages) &&
        (ISBN == otherBook.ISBN) && 
        (Genre == otherBook.Genre);
}