導讀
C#中變量可分爲值類型和引用類型,值類型儲存在棧中,引用類型儲存在堆中,棧中儲存在堆中的引用地址,List泛型的Contais在比較值類型時,直接比較值,但是在比較引用類型時,比較的是引用地址。
- 問題引入
實際開發中,我們經常會把同類型的一系列對象封裝到List集合中,當我們有需要在封裝對象到List集合中時,排除重複的對象,這時直接使用
if(!List.Contains(obj))
{
List.Add(bj);
}
List.Contains(obj)返回false時 ,我們給集合中添加,這種邏輯是沒有問題的,List.Contains(obj)比較的是:原來List集合中的對象的儲存地址和當前需要添加對象obj在堆中儲存的地址 ,所以即便有兩個對象相等,但是它們儲存的地址不同,所以List.Contains仍然返回false
解決方案
List.Contains(obj)調用的是obj對象對應的類的Equals()方法,我們可以按需要重寫這個方法和GetHashCode()方法,即可按自己的需求來定義Contains()比較方式。案例
public class Person
{
private string Number;
private string personName;
public Person(string name, string Number)
{
this.personName = name;
this.Number= Number;
}
public bool Equals(Person p)
{
//按需求定製自己需要的比較方式
return (this.personName == p.personName && this.Number == p.Number);
}
public override int GetHashCode()
{
return this.Number.GetHashCode();
}
}
public class Example
{
public static void Main()
{
Person p1 = new Person("John", "63412895");
Person p2 = new Person("Jack", "63412895");
List<Person> List = new List<Person>();
List.Add(p1);
List.Add(p2);
Person p3 = new Person("John", "63412895");
if(!List.Contains(p3))//沒有重寫前函數返回false,現在返回true
{
List.Add(p3);
}
}
}