ObservableCollection.Contains () is not working 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 is he adding x = "a", y = "1"in ListView?

If I change ObservableCollectionto Listor Collection, it does the same.

+5
source share
4 answers

The Contains method uses the Equals on object, and it just checks that the memory addresses are different.

Think about 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 then visits the strongly typed Equals method in your class, and this will lead to the behavior you are after.

NOTE: the string class ALSO inherits from IEquatable from T, and this is what allows the equality operator to work with the contents of the string rather than the address of the string.

+18
source

CX:

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

CY:

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

.

, , Linq.

+3

"a" != "a". , .

Contains()will check the memory addresses, not the actual contents. You cannot insert the same object twice, but "a"- this is not the same object as "a"(at least not here).

+2
source

All Articles