### Equals是virtual方法,可以overide修改方法 :::warning 如果想要讓所有衍生型別使用Object的Equals方法,那麼它的參數就必須設計成object型別。因為object是參考類型,所以如果傳遞一個值類型的參數,那麼該參數將被裝箱,這就會造成效能損失。此外,將object類型設為參數也意味著型別安全性的缺失。解決裝箱和類型安全性問題的一個方法是定義一個新的Equals方法,該方法接受一個和待比較類型相同類型的參數。但這會面臨另一個新的問題,那就是:定義強類型的方法和OOP中的繼承存在根本的衝突。因為Object基底類別根本無法知道派生類別的型別,所以我們不能在Object基底類別中定義一個強型別的Equals方法 ::: ``` class Person { public int Id { get; init; } public string Name { get; init; } public Person(int id, string name) { Id = id; Name = name; } public override bool Equals(object? obj) { return obj is Person person && Id == person.Id; } // override object.GetHashCode } ``` :::success 這時可以使用IEquatable<T>,IEquatable<T> 是一個泛型介面,用於比較兩個物件是否相等。實作 IEquatable<T> 的好處是可以提高效能,因為它可以避免裝箱(boxing)和拆箱(unboxing)的開銷。此外,實作 IEquatable<T> 還可以提高型別安全性,因為它可以避免使用 Object.Equals(Object) 方法時的型別轉換錯誤。 如果需要比較自定義的類型,建議實作 IEquatable<T> 介面。這樣可以讓你的程式碼更加高效和可靠 ::: ``` class Person : IEquatable<Person> { public int Id { get; set; } public string Name { get; set; } public Person(int id, string name) { Id = id; Name = name; } public override bool Equals(object? obj) { return obj is Person person && Equals(person); } public bool Equals(Person? other) { return Id == other.Id; } } ```