/// <summary> /// Add object and return the index position. /// </summary> public int Add(T obj) { // ... check for unused indexes first ... if (_UnusedIndexes.Count > 0) { var lastIndex = _UnusedIndexes.Count - 1; var i = _UnusedIndexes[lastIndex]; _UnusedIndexes.RemoveAt(lastIndex); _Objects[i] = new _ObjectItem { Object = obj, ValidObjectIndex = _ValidObjects.Count }; _ValidObjects.Add(new _ValidObjectItem { Object = obj, ObjectIndex = i }); return(i); } else { var i = _Objects.Count; _Objects.Add(new _ObjectItem { Object = obj, ValidObjectIndex = _ValidObjects.Count }); _ValidObjects.Add(new _ValidObjectItem { Object = obj, ObjectIndex = i }); return(i); } }
/// <summary> /// Removes the object at the given index and sets the entry to 'default(T)' (which is usually 0 or null). /// </summary> public void Remove(int objIndex) { if (objIndex < 0 || objIndex >= _Objects.Count) { throw new IndexOutOfRangeException("objIndex = " + objIndex); } _ObjectItem itemRemoved = _Objects[objIndex]; if (itemRemoved.ValidObjectIndex == -1) { return; // (already deleted, nothing to do) } if (objIndex == _Objects.Count - 1) // (if removing from end, simply "pop" it) { _Objects.RemoveAt(objIndex); } else // (clear this entry and record it for reuse) { _Objects[objIndex] = new _ObjectItem { Object = default(T), ValidObjectIndex = -1 }; _UnusedIndexes.Add(objIndex); } // ... swap valid-object-list entry with end and remove it ... var voLastIndex = _ValidObjects.Count - 1; if (itemRemoved.ValidObjectIndex != voLastIndex) // (if the item removed references the last "valid object" entry, just simply remove it [skip the block]) { var voEnd = _ValidObjects[voLastIndex]; _ValidObjects[itemRemoved.ValidObjectIndex] = voEnd; // (move end entry in place of removed item) var itemToUpdate = _Objects[voEnd.ObjectIndex]; // (need to update the indexed object's "valid object" index via the link-back index) itemToUpdate.ValidObjectIndex = itemRemoved.ValidObjectIndex; _Objects[voEnd.ObjectIndex] = itemToUpdate; } _ValidObjects.RemoveAt(voLastIndex); // (last item is moved down now in place of the deleted object, so this just really decrements the count.) }