Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List.Contains fails on object comparison

I have a class "Class1" that has a string variable "sText" in .NET 2.0. I have created a list of object of that class "lstClass1". It stores many objects of that class after setting its string variable.

Complete code is:

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 = "";
}

Now, the problem is that I only want to add class objects that has string with unique text value. For example, if lstClass1 already has an object with string variable value "text1" then it should not allow addition of an object that also has "text1". So, I wrote code:

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

But it always allows the text "text1" to be added even when there is already an object in the list with "text1" string. My assumption was that on first button click event "button1_Click" the object will be added because the list is empty but on next button click the List.Contains function will check if there is already an object in the list with string variable "text1" and if found then it will not be added. But it always allow to add object with text "text1" even if it is already present in the list.

Please note: I have not taken a simple list of strings or an of string because I want to explain my large problem of list, classes and objects in a simple way.

like image 977
Computer User Avatar asked Feb 07 '14 10:02

Computer User


2 Answers

Use Any() method:

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

This code:

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

Could only work if you would provide the Equals() and GetHashCode() methods for your Class1 to enable making the comparisons between two objects of this class. To achieve this your class should implement the IEquatable interface. So your Class1 could look like this:

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();
    }
}
like image 193
Paweł Bejger Avatar answered Sep 19 '22 00:09

Paweł Bejger


Contains will only work correctly if you implement IEquatable in your case.

You may use the following code instead:

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();
}

Uncomment the commented lines and you will see the difference.

like image 27
Johnny Avatar answered Sep 19 '22 00:09

Johnny