This is an old question, and I have already used the existing answer myself. But playing with KeyedCollection <> again, I realized that the Remove-and-Then-Add method is less efficient than the method that I have just implemented. The problem is that the Remove () method searches linearly in the Sheet and then moves the rest of the list to a single entry on the left. The technique presented here also searches the List linearly, but at least it avoids the bias of the rest of the list.
NB. This applies only when the replacement element has the same key as the element that it should replace.
/// <summary> /// Derived (but still abstract) version of KeyedCollection{} to provide a couple of extra /// services, in particular AddOrReplace() and Replace() methods. /// </summary> public abstract class KeyedList<TKey, TItem> : KeyedCollection<TKey, TItem> { /// <summary> /// Property to provide access to the "hidden" List{} in the base class. /// </summary> public List<TItem> BaseList { get { return base.Items as List<TItem>; } } /// <summary> /// Method to add a new object to the collection, or to replace an existing one if there is /// already an object with the same key in the collection. /// </summary> public void AddOrReplace(TItem newObject) { int i = GetItemIndex(newObject); if (i != -1) base.SetItem(i, newObject); else base.Add(newObject); } /// <summary> /// Method to replace an existing object in the collection, ie, an object with the same key. /// An exception is thrown if there is no existing object with the same key. /// </summary> public void Replace(TItem newObject) { int i = GetItemIndex(newObject); if (i != -1) base.SetItem(i, newObject); else throw new Exception("Object to be replaced not found in collection."); } /// <summary> /// Method to get the index into the List{} in the base collection for an item that may or may /// not be in the collection. Returns -1 if not found. /// </summary> private int GetItemIndex(TItem itemToFind) { TKey keyToFind = GetKeyForItem(itemToFind); return BaseList.FindIndex((TItem existingItem) => GetKeyForItem(existingItem).Equals(keyToFind)); } }
source share