So I was looking through the implementation of SortedList<TKey, TValue> and the implementation of Add (which calls Insert shown below) really surprised me.
The Add method does the obvious binary search to determine the index in which the KVP should go, but the Insert seems as if it could be improved significantly (albeit on larger scales of course):
private void Insert(int index, TKey key, TValue value)
{
  if (this._size == this.keys.Length)
    this.EnsureCapacity(this._size + 1);
  if (index < this._size)
  {
    Array.Copy((Array) this.keys, index, (Array) this.keys, index + 1, this._size - index);
    Array.Copy((Array) this.values, index, (Array) this.values, index + 1, this._size - index);
  }
  this.keys[index] = key;
  this.values[index] = value;
  ++this._size;
  ++this.version;
}
If I'm reading this correctly, and I reserve the right to be wrong at all times, this is an O(2n) operation.
It seems to me that the values should be implemented with pointers. Kind of like a LinkedList in relation to the value from the key, but not linked in that it doesn't support random access. More so the key is simply linked to its value. The get operation wouldn't be any slower, and neither would the remove because we have the pointer, but the add operation would be O(n) now instead.
Can somebody shed some light on why the decision may have gone this direction?
 
     
    