private void RemoveAt(int position)
{
int cacheSize = m_objs.Length;
int lastVacantPosition = position;
for (int next = (position == cacheSize - 1) ? 0 : position + 1; next != position; next++)
{
if (m_objs[next] == null)
{
m_objs[lastVacantPosition] = null;
m_ids[lastVacantPosition] = 0;
m_isWrapped[lastVacantPosition] = false;
return;
}
int nextStartPosition = ComputeStartPosition(m_objs[next]);
// If we wrapped while placing an object, then it must be that the start position wasn't wrapped to begin with
bool isNextStartPositionWrapped = next < position && !m_isWrapped[next];
bool isLastVacantPositionWrapped = lastVacantPosition < position;
// We want to avoid moving objects in the cache if the next bucket position is wrapped, but the last vacant position isn't
// and we want to make sure to move objects in the cache when the last vacant position is wrapped but the next bucket position isn't
if ((nextStartPosition <= lastVacantPosition && !(isNextStartPositionWrapped && !isLastVacantPositionWrapped)) ||
(isLastVacantPositionWrapped && !isNextStartPositionWrapped))
{
m_objs[lastVacantPosition] = m_objs[next];
m_ids[lastVacantPosition] = m_ids[next];
// A wrapped object might become unwrapped if it moves from the front of the array to the end of the array
m_isWrapped[lastVacantPosition] = m_isWrapped[next] && next > lastVacantPosition;
lastVacantPosition = next;
}
if (next == (cacheSize - 1))
{
next = -1;
}
}
// m_obj must ALWAYS have at least one slot empty (null).
DiagnosticUtility.DebugAssert("Object table overflow");
throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.ObjectTableOverflow)));
}