What's wrong with using List for that? That's nothing but an implementation of IList and you can do the partitioning yourself. But if you want to do it transparently:
Implement IList (it's just an interface, nothing special about it. Maybe I don't understand the question?) and back it up by arrays of your desired size. Your Get()
would then take the index / sizeOfArrays
as index of the array containing the desired item and return the index % sizeOfArrays
th item in that array.
For fun, because it's a lazy friday, I wrote something up. Note:
- I didn't test it
- I cannot comment on the correctnes of your quoted claims that this might help avoiding memory fragmentation, I just blindly looked at your request
- I don't know if List or any other collection is already smart enough to do just that
- I made some decisions that might not be right for you (i.e. you cannot blindly drop this in your code if you're using arrays now. Look at the
Item
implementation, especially the setter, for example
That said, here's a starting point that reduced my pre-weekend motivational deficit. I left some interesting methods as exercise to the dear reader (or OP).. ;-)
public class PartitionList<T> : IList<T> {
private readonly int _maxCountPerList;
private readonly IList<IList<T>> _lists;
public PartitionList(int maxCountPerList) {
_maxCountPerList = maxCountPerList;
_lists = new List<IList<T>> { new List<T>() };
}
public IEnumerator<T> GetEnumerator() {
return _lists.SelectMany(list => list).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}
public void Add(T item) {
var lastList = _lists[_lists.Count - 1];
if (lastList.Count == _maxCountPerList) {
lastList = new List<T>();
_lists.Add(lastList);
}
lastList.Add(item);
}
public void Clear() {
while (_lists.Count > 1) _lists.RemoveAt(1);
_lists[0].Clear();
}
public bool Contains(T item) {
return _lists.Any(sublist => sublist.Contains(item));
}
public void CopyTo(T[] array, int arrayIndex) {
// Homework
throw new NotImplementedException();
}
public bool Remove(T item) {
// Evil, Linq with sideeffects
return _lists.Any(sublist => sublist.Remove(item));
}
public int Count {
get { return _lists.Sum(subList => subList.Count); }
}
public bool IsReadOnly {
get { return false; }
}
public int IndexOf(T item) {
int index = _lists.Select((subList, i) => subList.IndexOf(item) * i).Max();
return (index > -1) ? index : -1;
}
public void Insert(int index, T item) {
// Homework
throw new NotImplementedException();
}
public void RemoveAt(int index) {
// Homework
throw new NotImplementedException();
}
public T this[int index] {
get {
if (index >= _lists.Sum(subList => subList.Count)) {
throw new IndexOutOfRangeException();
}
var list = _lists[index / _maxCountPerList];
return list[index % _maxCountPerList];
}
set {
if (index >= _lists.Sum(subList => subList.Count)) {
throw new IndexOutOfRangeException();
}
var list = _lists[index / _maxCountPerList];
list[index % _maxCountPerList] = value;
}
}
}