---
# System prepended metadata

title: C#內建方法Equals
tags: [C#]

---

### 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<Ｔ>，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;
    }

}
```