简体   繁体   中英

How can I detect adds to a generic list in C# 4.0?

I have a subclass of List<Location> called LocationList . This is a convenient way for us to add other properties (like IsExpanded and such that we can use in the UI. Good enough. But now, we want each location to be aware of its parent. As such, we need to be notified when something is added to LocationList, but you can't override Add and Remove . While we can use ObservableCollection, that's more of a View/ViewModel construct. This is pure model data.

Sure we could manually set the parent when adding it to the collection, but I hate non-automated logic like that as there's nothing to enforce its set correctly. Letting the collection (well, List) automatically say 'Hey... you're being added, so I'll set your parent to the class that owns me." is what I'm after.

My thought is to instead of subclass List<Location> to instead just create a straight class that uses a List<Location> internally, and then I can simply expose my own Add/Remove methods and handle the adjustments to 'Parent' in there. However, doing so breaks being able to enumerate over the internal collection since it's inside.

That said, is there any way to either listen to changes to List<Location> , or at least delegate its IEnumerable interface from the wrapped object to its wrapper?

Change your LocationList to inherit from Collection<Location> instead. I don't know why List<T> isn't sealed, but it's not extendable.

Source: Framework Design Guidelines, Second Edition, Page 251:

List<T> is optimized for performance and power at the cost of cleanness of the APIs and flexibility.

List<T> has protected members InsertItem<T> , RemoveItem<T> etc that you can override in your derived class to do what you want.

** UPDATE **

Actually the above is incorrect, it's Collection<T> that has these protected methods. In general, when deriving custom List classes, it is recommended to derive from Collection<T> rather than List<T> .

See this answer .

My thought is to instead of subclass List to instead just create a straight class that uses a List internally, and then I can simply expose my own Add/Remove methods and handle the adjustments to 'Parent' in there. However, doing so breaks being able to enumerate over the internal collection since it's inside.

You can still implement IEnumerable<Location> on your custom collection. Use the List<> as the internal implementation detail of the class, and you can allow enumeration via the interface.

class LocationList : IEnumerable<Location>
{
    List<Location> _list; // initialize somewhere

    public IEnumerator<Location> GetEnumerator() 
    {
         return _list.GetEnumerator();
    }

    IEnumerable.IEnumerator GetEnumerator() 
    {
         return this.GetEnumerator();
    }

    // ... your other custom properties and methods
}

Try the generic BindingList<T> , which raises events when items are added and removed.

However, doing so breaks being able to enumerate over the internal collection since it's inside.

This is not true assuming you follow proper technique and implement IEnumerable and ICollection

But I would use Observable collection instead of reinventing the wheel.

And of course you can use Reactive extensions to do what you need.

You can either using Observer pattern

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM