2014-02-07 3 views
5

У меня есть класс «Class1», который имеет строковую переменную «sText» в .NET 2.0. Я создал список объектов этого класса «lstClass1». Он сохраняет много объектов этого класса после установки его строковой переменной.List.Contains сбой при сравнении объектов

Полный код:

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     if (!lstClass1.Contains(new Class1("text1"))) 
      lstClass1.Add(new Class1("text1")); 
    } 

    public List<Class1> lstClass1 = new List<Class1>(); 
} 

public class Class1 
{ 
    public Class1(string sText) 
    { 
     this.sText = sText; 
    } 

    public string sText = ""; 
} 

Теперь проблема в том, что я только хочу, чтобы добавить объекты класса, который имеет строку с уникальным текстовым значением. Например, если lstClass1 уже имеет объект со значением переменной строки «text1», то он не должен допускать добавления объекта, который также имеет «text1». Итак, я написал код:

if (!lstClass1.Contains(new Class1("text1"))) 
    lstClass1.Add(new Class1("text1")); 

Но это позволяет всегда текст «text1» должны быть добавлены, даже если уже есть объект в списке с «TEXT1» строка. Мое предположение состояло в том, что при первом нажатии кнопки «button1_Click» объект будет добавлен, потому что список пуст, но при следующей кнопке нажмите «Функция List.Contains», чтобы проверить, есть ли уже объект в списке со строковой переменной «text1» и если он будет найден, он не будет добавлен. Но он всегда позволяет добавлять объект с текстом «text1», даже если он уже присутствует в списке.

Обратите внимание: я не взял простой список строк или строки, потому что я хочу объяснить мою большую проблему списка, классов и объектов простым способом.

Пожалуйста, помогите.

+1

Вы предоставили реализацию методов Equals и GetHashCode по умолчанию для Class1? – Oscar

+0

http://stackoverflow.com/questions/10454519/best-way-to-compare-two-complex-object – k06a

+0

Не знаете, почему вы не храните этот 'новый Class1 (« text1 »)' в новый класс Class1 '-typed variable, кстати. Нет необходимости строить его дважды. Просто постройте один раз, проверьте его на переменной, а затем сохраните его из переменной. – Nyerguds

ответ

7

Используйте Any() метод:

if (!lstClass1.Any(x => x.sText == "text1")) 
    lstClass1.Add(new Class1("text1")); 

Этот код:

if (!lstClass1.Contains(new Class1("text1"))) 
    lstClass1.Add(new Class1("text1")); 

Может работать только, если бы вы предоставить Equals() и GetHashCode() методы для Class1 для того, чтобы сделать сравнения между двумя объектами этого класс. Для этого ваш класс должен реализовать интерфейс IEquatable. Так что ваш Class1 может выглядеть следующим образом:

public class Class1 : IEquatable<Class1> 
{ 
    public Class1(string sText) 
    { 
     this.sText = sText; 
    } 

    public string sText = ""; 

    public bool Equals(Class1 other) 
    { 
     if (other == null) 
     return false; 

     if (this.sText == other.sText) 
     return true; 
     else 
     return false; 
    } 

    public override int GetHashCode() 
    { 
     return this.sText.GetHashCode(); 
    } 
} 
0

Это терпит неудачу, потому что список вызовов Equals на вашем экземпляре, и реализация по умолчанию выполняет проверку на равенство ссылок. Хотя ваш объект имеет значение свойства name, это экземпляр различия, поэтому ссылки не будут равны.

В Class1 переопределить метод Equals сравнить основные свойства

public override bool Equals(object other) 
{ 
    Class1 rhs=other as Class1; 
    if(rhs==null) return false; 

    return this.sText == rhs.sText; 
} 
0

Проблема вы столкнулись здесь между объектом и экземпляром. Когда вы проверяете следующее, вы в основном спрашиваете «есть в коллекции?»

!lstClass1.Contains(new Class1("text1")) 

Ну это, очевидно, не может быть, так как вы только что создали его. То, что вам нужно проверить, - это содержимое этого объекта. Самый простой способ сделать это - выполнить итерацию коллекции и проверить содержимое каждого объекта.

Это очень легко сделать с LINQ (хотя я не уверен, что он доступен для .NET 2.0):

!lstClass1.Any(i => i.Text == "text1") 

Другим решением было бы переписать GetHashCode() и Equals методы вашего Class1 рассмотреть два объекта как «равно», если их содержание одинаковы. и, таким образом, позволяют провести тщательное сравнение.

1

Содержит только правильные работы, если вы реализуете IEquatable в своем случае.

Вы можете использовать следующий код вместо:

public class Class1 //: IEquatable<Class1> 
{ 
    public string sText = ""; 
    public Class1(string sText) 
    { 
     this.sText = sText; 
    } 

    //public bool Equals(Class1 other) 
    //{ 
    // return this.sText == other.sText; 
    //} 
} 
static void Main(string[] args) 
{ 
    List<Class1> lstClass1 = new List<Class1>() { new Class1("text1") }; 
    if (!lstClass1.Contains(new Class1("text1"))) 
     lstClass1.Add(new Class1("text1")); 
    Console.WriteLine(lstClass1.Count); 
    Console.ReadKey(); 
} 

раскомментируйте строки комментариев, и вы увидите разницу.

Смежные вопросы