Elmo
Elmo

Reputation: 6471

ObservableCollection.Contains() Doesn't Work Correctly

Consider the following:

class Bind
{
    public string x { get; set; }
    public string y { get; set; }
}
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        ObservableCollection<Bind> cX = new ObservableCollection<Bind>();
        ObservableCollection<Bind> cY = new ObservableCollection<Bind>();
        cX.Add(new Bind { x = "a", y = "1" });
        cX.Add(new Bind { x = "b", y = "2" });
        cY.Add(new Bind { x = "a", y = "1" });
        foreach (var i in cX)
        {
            if (!cY.Contains(i)) { lv.Items.Add(i); } //lv is a ListView control
        }
    }
}

Why does it add x = "a", y = "1" to the ListView?

If I change ObservableCollection to List or Collection, it does the same.

Upvotes: 8

Views: 11293

Answers (4)

Gayot Fow
Gayot Fow

Reputation: 8792

The 'Contains' method uses the Equals on object, and this simply checks that the memory addresses are different.

Consider changing your class to this...

 class Bind : IEquatable<Bind> {
     public string x { get; set; }
     public string y { get; set; }
     public bool Equals(Bind other)
     {
         return x == other.x && y == other.y; 
     } 
}

Your loop will then visit the strongly typed Equals method in your class, and this will result in the behaviour you are after.

NOTE: the string class ALSO inherits from IEquatable of T and that is what allows the equality operator to operate on the content of the string rather than the address of the string.

Upvotes: 20

competent_tech
competent_tech

Reputation: 44931

Because that you have added that value set to CX:

cX.Add(new Bind { x = "a", y = "1" });

and to CY:

cY.Add(new Bind { x = "a", y = "1" });

And those are different objects.

If you want to see if a given key is present, you will need to change to a dictionary or use Linq.

Upvotes: 2

Tom van der Woerdt
Tom van der Woerdt

Reputation: 29975

Because "a" != "a". At least, not always.

Contains() will check memory addresses, not the actual contents. You cannot insert the same object twice, and "a" isn't the same object as "a" (at least, not here).

Upvotes: 1

Related Questions