嘗試從集合移除對象後,對象仍留在集合中?這是因為 List<T>.Remove 使用預設相等比較器 (EqualityComparer<T>.Default),對引用類型比較的是引用地址而非內容。
IList<Product> products = new List<Product>();
products.Add(GetProduct("1412")); // 實例 A
products.Remove(GetProduct("1412")); // 實例 B (新實例)
Console.WriteLine(products.Count); // 輸出 1 (未移除!)
GetProduct 每次從 DB 讀取返回新實例。Product 未重寫 Equals/GetHashCode,繼承自 Object,故比較引用。
List<T>.Remove → EqualityComparer<T>.Default。T 實作 IEquatable<T>,使用其 Equals(T)。Object.Equals (引用相等) + Object.GetHashCode。因此,兩個內容相同但引用不同的 Product 實例被視為不相等,Remove 失效。
public class Product : IEquatable<Product> {
public string ID { get; }
public Product(string id) { ID = id; }
public bool Equals(Product other) {
return other != null && ID == other.ID;
}
public override bool Equals(object obj) => Equals(obj as Product);
public override int GetHashCode() => ID.GetHashCode();
}
public class Product {
public string ID { get; }
public Product(string id) { ID = id; }
public override bool Equals(object obj) {
return obj is Product other && ID == other.ID;
}
public override int GetHashCode() => ID.GetHashCode();
}
IEquatable<T> + 重寫 Equals/GetHashCode + 運算符 ==/!=)。ID) 作為相等依據,而非所有字段。修復後,products.Remove(new Product("1412")) 即可正常移除內容相同的實例。