The following class is a helper to avoid OutOfMemoryException
exceptions being thrown when the list is to large so that it is added onto the large objects heap. To do this it adds the items onto the heap as smaller arrays contained inside of a list.
Some quick notes:
- I prefer not to use var.
- The constant in all caps is a company standard.
using System;
using System.Collections;
using System.Collections.Generic;
namespace Helpers.Collections
{
public class ChunkedList<T> : IEnumerable<T>, IDisposable
{
private const int DEFAULT_CHUNK_SIZE = 4096;
private readonly int _nChunkSize;
private IList<T[]> _alInternalCollection;
private int _nCount;
private bool _bTIsDisposable;
public int Count
{
get
{
return _nCount;
}
}
public ChunkedList() : this(DEFAULT_CHUNK_SIZE) { }
public ChunkedList(int chunkSize)
{
_alInternalCollection = new List<T[]>();
_nChunkSize = chunkSize;
_nCount = 0;
_bTIsDisposable = typeof(IDisposable).IsAssignableFrom(typeof(T));
}
public void Dispose()
{
this.Clear();
}
public T this[int index]
{
get
{
if (index < 0 || index >= _nCount)
{
throw new IndexOutOfRangeException();
}
int nChunk = index / _nChunkSize;
int nChunkIndex = index % _nChunkSize;
return _alInternalCollection[nChunk][nChunkIndex];
}
set
{
if (index < 0 || index >= _nCount)
{
throw new IndexOutOfRangeException();
}
int nChunk = index / _nChunkSize;
int nChunkIndex = index % _nChunkSize;
T oldItem = _alInternalCollection[nChunk][nChunkIndex];
_alInternalCollection[nChunk][nChunkIndex] = value;
if (_bTIsDisposable)
{
(oldItem as IDisposable).Dispose();
}
}
}
public void Add(T item)
{
int nChunk = _nCount / _nChunkSize;
int nChunkIndex = _nCount % _nChunkSize;
if (nChunkIndex == 0)
{
_alInternalCollection.Add(new T[_nChunkSize]);
}
_alInternalCollection[nChunk][nChunkIndex] = item;
_nCount++;
}
public void AddRange(IEnumerable<T> items)
{
if (items == null)
{
throw new ArgumentNullException("items");
}
foreach (T item in items)
{
this.Add(item);
}
}
public void Clear()
{
if (_bTIsDisposable)
{
foreach (T[] array in _alInternalCollection)
{
foreach (T t in array)
{
(t as IDisposable).Dispose();
}
}
}
_alInternalCollection.Clear();
_nCount = 0;
}
public bool Contains(T item)
{
foreach (T[] array in _alInternalCollection)
{
foreach (T t in array)
{
if (item.Equals(t))
{
return true;
}
}
}
return false;
}
public IEnumerator<T> GetEnumerator()
{
foreach (T[] array in _alInternalCollection)
{
foreach (T t in array)
{
yield return t;
}
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
public int IndexOf(T item)
{
for (int i = 0; i < _alInternalCollection.Count; ++i)
{
for (int j = 0; j < _alInternalCollection[i].Length; ++j)
{
if (item.Equals(_alInternalCollection[i][j]))
{
return ((i * _nChunkSize) + j);
}
}
}
return -1;
}
}
}