ObservableCollection IndexOf

Как то раз, необходимо было выяснить, содержит ли коллекция ObservableCollection элемент. Благо, у ObservableCollection есть метод IndexOf который возвращает индекс элемента, если он есть в коллекции. Но не всё так гладко. Рассмотрим пример ниже:

using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.ObjectModel;

namespace ObservableCollectionIndexOf
{
    class Program
    {
        static ObservableCollection<Data> DataCollection;
        static Data _data;

        static void Main(string[] args)
        {
            DataCollection = new ObservableCollection<Data>();

            //заполняем коллекцию
            for (int i = 0; i < 10; i++)
            {
                _data = new Data(i);
                DataCollection.Add(_data);
                Console.WriteLine(DataCollection.IndexOf(_data));
            }

            _data = new Data(4);
            Console.WriteLine(DataCollection.IndexOf(_data));
            Console.ReadKey();
        }
    }

    class Data
    {
        public int Id { get; set; }
        public string Name { get; set; }

        public Data(int Id)
        {
            this.Id = Id;
            Name = "Name " + Id;
        }
    }
}

Результат оказывается немножко другим, чем можно ожидать. В случае, когда проверяется объект, который был добавлен в коллекцию (проверка сразу после добавления), то возвращается индекс добавленного элемнта. Когда же мы создаем новый элемент и проверяем его наличие в коллекции, то получаем результат -1, то есть – элемент не найден. Оказывается, IndexOf проверяет совпдадение ссылок на объекты, а не самих объектов.

Я нашёл несколько решений этой проблемы. Одна из них, это сделать класс Data структурой, но это не всегда подходит разработчику. Второе решение – реализовать в классе интерфейс IEquatable. Также, хорошей идеей будет переопределить метод GetHashCode. В результате имеем класс и отлично работающий метод IndexOf

class Data : IEquatable<Data>
{
    public int Id { get; set; }
    public string Name { get; set; }

    public Data(int Id)
    {
        this.Id = Id;
        Name = "Name " + Id;
    }

    #region IEquatable<Data> Members

    public bool Equals(Data other)
    {
        if (this.Id == other.Id)
            return true;
        return false;
    }

    #endregion

    public override int GetHashCode()
    {
        return Id.GetHashCode();
    }
}

Исходники: [download id=”19″]

Leave a Reply

Your email address will not be published. Required fields are marked *

http://csharpcoding.org/wp-content/plugins/wp-monalisa/icons/wpml_bye.gif  http://csharpcoding.org/wp-content/plugins/wp-monalisa/icons/wpml_good.gif  http://csharpcoding.org/wp-content/plugins/wp-monalisa/icons/wpml_negative.gif  http://csharpcoding.org/wp-content/plugins/wp-monalisa/icons/wpml_scratch.gif  http://csharpcoding.org/wp-content/plugins/wp-monalisa/icons/wpml_wacko.gif  http://csharpcoding.org/wp-content/plugins/wp-monalisa/icons/wpml_yahoo.gif 
http://csharpcoding.org/wp-content/plugins/wp-monalisa/icons/wpml_cool.gif  http://csharpcoding.org/wp-content/plugins/wp-monalisa/icons/wpml_heart.gif  http://csharpcoding.org/wp-content/plugins/wp-monalisa/icons/wpml_rose.gif  http://csharpcoding.org/wp-content/plugins/wp-monalisa/icons/wpml_smile.gif  http://csharpcoding.org/wp-content/plugins/wp-monalisa/icons/wpml_whistle3.gif  http://csharpcoding.org/wp-content/plugins/wp-monalisa/icons/wpml_yes.gif 
http://csharpcoding.org/wp-content/plugins/wp-monalisa/icons/wpml_cry.gif  http://csharpcoding.org/wp-content/plugins/wp-monalisa/icons/wpml_mail.gif  http://csharpcoding.org/wp-content/plugins/wp-monalisa/icons/wpml_sad.gif  http://csharpcoding.org/wp-content/plugins/wp-monalisa/icons/wpml_unsure.gif  http://csharpcoding.org/wp-content/plugins/wp-monalisa/icons/wpml_wink.gif