Skip to content

Instantly share code, notes, and snippets.

@Nayruden
Created March 30, 2010 21:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Nayruden/349633 to your computer and use it in GitHub Desktop.
Save Nayruden/349633 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Collections;
public class Slice<T> : IList<T>
{
private IList<T> backing_array;
private readonly int start;
private readonly int _count;
void checkArgs(IList<T> backing_array, int start, int end)
{
if (start < 0 || start >= backing_array.Count || end <= 0 || end > backing_array.Count)
throw new IndexOutOfRangeException();
if (end <= start)
throw new ArgumentOutOfRangeException("end", end, "Ending index must be greater than starting index");
}
public Slice(IList<T> backing_array, int start, int end)
{
checkArgs(backing_array, start, end);
this.backing_array = backing_array;
this.start = start;
this._count = end - start;
}
public Slice(Slice<T> slice, int start, int end)
{
checkArgs(slice, start, end);
this.backing_array = slice.backing_array;
this.start = slice.start + start;
this._count = end - start;
}
public Slice<T> this[int start, int end]
{
get { return new Slice<T>(this, start, end); }
}
public T this[int index]
{
get
{
if (index >= 0 && index < Count)
return backing_array[index + start];
throw new IndexOutOfRangeException();
}
set
{
if (index >= 0 && index < Count)
backing_array[index + start] = value;
throw new IndexOutOfRangeException();
}
}
public int IndexOf(T item)
{
for (int i = 0; i < Count; i++)
if (EqualityComparer<T>.Default.Equals(item, this[i]))
return i;
return -1;
}
public bool Contains(T item)
{
return IndexOf(item) >= 0;
}
public void CopyTo(T[] array, int arrayIndex)
{
for (int i = 0; i < Count; i++)
array[arrayIndex + i] = this[i];
}
public int Count
{
get { return _count; }
}
public IEnumerator<T> GetEnumerator()
{
for (int i = 0; i < Count; i++)
yield return backing_array[i + start];
}
#region Explicit/Hidden Implementations
void IList<T>.Insert(int index, T item)
{
throw new NotSupportedException();
}
void IList<T>.RemoveAt(int index)
{
throw new NotSupportedException();
}
void ICollection<T>.Add(T item)
{
throw new NotSupportedException();
}
void ICollection<T>.Clear()
{
throw new NotSupportedException();
}
bool ICollection<T>.IsReadOnly
{
get { return true; }
}
bool ICollection<T>.Remove(T item)
{
throw new NotSupportedException();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
}
using System;
using System.Collections.Generic;
using NUnit.Framework;
using System.Collections;
using System.Linq;
[TestFixture]
class SliceTest
{
[Test]
public void BasicSlice()
{
int[] range = { 1, 2, 3, 4, 5 };
var slice = new Slice<int>(range, 0, range.Length);
Assert.AreEqual(range.Length, slice.Count);
Assert.AreEqual(range, slice);
// Test indexer
Assert.AreEqual(range[0], slice[0]);
Assert.AreEqual(range[1], slice[1]);
Assert.AreEqual(range[2], slice[2]);
Assert.AreEqual(range[3], slice[3]);
Assert.AreEqual(range[4], slice[4]);
// Test enumeration
int num = 1;
foreach (var i in slice)
Assert.AreEqual(i, num++);
// Test index of
Assert.AreEqual(slice.IndexOf(1), 0);
Assert.AreEqual(slice.IndexOf(4), 3);
Assert.AreEqual(slice.IndexOf(5), 4);
Assert.AreEqual(slice.IndexOf(0), -1);
// Test contains
Assert.True(slice.Contains(1));
Assert.True(slice.Contains(2));
Assert.True(slice.Contains(5));
Assert.False(slice.Contains(0));
slice = slice[1, slice.Count];
Assert.AreEqual(range.Length - 1, slice.Count);
Assert.AreEqual(range.Skip(1), slice);
slice = slice[0, slice.Count - 1];
Assert.AreEqual(range.Length - 2, slice.Count);
Assert.AreEqual(range.Skip(1).Take(3), slice);
// Test copy to
int[] copy = new int[5];
new Slice<int>(range, 1, range.Length - 1).CopyTo(copy, 2);
Assert.AreEqual(range.Skip(1).Take(3), copy.Skip(2));
}
[Test]
public void Asserts()
{
int[] range = { 1, 2, 3, 4, 5 };
int i;
var slice = new Slice<int>(range, 0, range.Length);
Assert.Throws(typeof(IndexOutOfRangeException), () => slice[-1] = 1);
Assert.Throws(typeof(IndexOutOfRangeException), () => slice[5] = 1);
Assert.Throws(typeof(IndexOutOfRangeException), () => i = slice[-1]);
Assert.Throws(typeof(IndexOutOfRangeException), () => i = slice[5]);
Assert.Throws(typeof(IndexOutOfRangeException), () => slice = slice[-1, 1]);
Assert.Throws(typeof(IndexOutOfRangeException), () => slice = slice[slice.Count, slice.Count]);
Assert.Throws(typeof(IndexOutOfRangeException), () => slice = slice[0, 0]);
Assert.Throws(typeof(IndexOutOfRangeException), () => slice = slice[0, slice.Count + 1]);
Assert.Throws(typeof(ArgumentOutOfRangeException), () => slice = slice[2, 2]);
slice = slice[1, slice.Count - 1];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment