How to handle add to list event?

后端 未结 10 2383
伪装坚强ぢ
伪装坚强ぢ 2020-11-29 22:55

I have a list like this:

List list = new List

How to handle adding new position to this list?

When

10条回答
  •  长情又很酷
    2020-11-29 23:38

    To be clear: If you only need to observe the standard-functionalities you should use ObservableCollection(T) or other existing classes. Never rebuild something you already got.

    ..But.. If you need special events and have to go deeper, you should not derive from List! If you derive from List you can not overloead Add() in order to see every add.

    Example:

    public class MyList : List
    {
        public void Add(T item) // Will show us compiler-warning, because we hide the base-mothod which still is accessible!
        {
            throw new Exception();
        }
    }
    
    public static void Main(string[] args)
    {
        MyList myList = new MyList(); // Create a List which throws exception when calling "Add()"
        List list = myList; // implicit Cast to Base-class, but still the same object
    
        list.Add(1);              // Will NOT throw the Exception!
        myList.Add(1);            // Will throw the Exception!
    }
    

    It's not allowed to override Add(), because you could mees up the functionalities of the base class (Liskov substitution principle).

    But as always we need to make it work. But if you want to build your own list, you should to it by implementing the an interface: IList.

    Example which implements a before- and after-add event:

    public class MyList : IList
    {
        private List _list = new List();
    
        public event EventHandler BeforeAdd;
        public event EventHandler AfterAdd;
    
        public void Add(T item)
        {
            // Here we can do what ever we want, buffering multiple events etc..
            BeforeAdd?.Invoke(this, null);
            _list.Add(item);
            AfterAdd?.Invoke(this, null);
        }
    
        #region Forwarding to List
        public T this[int index] { get => _list[index]; set => _list[index] = value; }
        public int Count => _list.Count;
        public bool IsReadOnly => false;
        public void Clear() => _list.Clear();
        public bool Contains(T item) => _list.Contains(item);
        public void CopyTo(T[] array, int arrayIndex) => _list.CopyTo(array, arrayIndex);
        public IEnumerator GetEnumerator() => _list.GetEnumerator();
        public int IndexOf(T item) => _list.IndexOf(item);
        public void Insert(int index, T item) => _list.Insert(index, item);
        public bool Remove(T item) => _list.Remove(item);
        public void RemoveAt(int index) => _list.RemoveAt(index);
        IEnumerator IEnumerable.GetEnumerator() => _list.GetEnumerator();
        #endregion
    }
    

    Now we've got all methods we want and didn't have to implement much. The main change in our code is, that our variables will be IList instead of List, ObservableCollection or what ever.

    And now the big wow: All of those implement IList:

    IList list1 = new ObservableCollection();
    IList list2 = new List();
    IList list3 = new int[10];
    IList list4 = new MyList();
    

    Which brings us to the next point: Use Interfaces instead of classes. Your code should never depend on implementation-details!

提交回复
热议问题