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