[Serializable]
public struct ArraySegment<T> : IList<T>, IReadOnlyList<T>
{
+ // Do not replace the array allocation with Array.Empty. We don't want to have the overhead of
+ // instantiating another generic type in addition to ArraySegment<T> for new type parameters.
+ public static ArraySegment<T> Empty { get; } = new ArraySegment<T>(new T[0]);
+
private readonly T[] _array;
private readonly int _offset;
private readonly int _count;
public int Count => _count;
- public Enumerator GetEnumerator()
+ public T this[int index]
{
- if (_array == null)
- ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NullArray);
- Contract.EndContractBlock();
+ get
+ {
+ if ((uint)index >= (uint)_count)
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index);
+ }
+ return _array[_offset + index];
+ }
+ set
+ {
+ if ((uint)index >= (uint)_count)
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index);
+ }
+
+ _array[_offset + index] = value;
+ }
+ }
+
+ public Enumerator GetEnumerator()
+ {
+ ThrowInvalidOperationIfDefault();
return new Enumerator(this);
}
return hash;
}
+ public void CopyTo(T[] destination) => CopyTo(destination, 0);
+
+ public void CopyTo(T[] destination, int destinationIndex)
+ {
+ ThrowInvalidOperationIfDefault();
+ System.Array.Copy(_array, _offset, destination, destinationIndex, _count);
+ }
+
+ public void CopyTo(ArraySegment<T> destination)
+ {
+ ThrowInvalidOperationIfDefault();
+ destination.ThrowInvalidOperationIfDefault();
+
+ if (_count > destination._count)
+ {
+ ThrowHelper.ThrowArgumentException_DestinationTooShort();
+ }
+
+ System.Array.Copy(_array, _offset, destination._array, destination._offset, _count);
+ }
+
public override bool Equals(Object obj)
{
if (obj is ArraySegment<T>)
return obj._array == _array && obj._offset == _offset && obj._count == _count;
}
+ public ArraySegment<T> Slice(int index)
+ {
+ ThrowInvalidOperationIfDefault();
+
+ if ((uint)index > (uint)_count)
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index);
+ }
+
+ return new ArraySegment<T>(_array, _offset + index, _count - index);
+ }
+
+ public ArraySegment<T> Slice(int index, int count)
+ {
+ ThrowInvalidOperationIfDefault();
+
+ if ((uint)index > (uint)_count || (uint)count > (uint)(_count - index))
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index);
+ }
+
+ return new ArraySegment<T>(_array, _offset + index, count);
+ }
+
+ public T[] ToArray()
+ {
+ ThrowInvalidOperationIfDefault();
+
+ if (_count == 0)
+ {
+ return Empty._array;
+ }
+
+ var array = new T[_count];
+ System.Array.Copy(_array, _offset, array, 0, _count);
+ return array;
+ }
+
public static bool operator ==(ArraySegment<T> a, ArraySegment<T> b)
{
return a.Equals(b);
return !(a == b);
}
+ public static implicit operator ArraySegment<T>(T[] array) => new ArraySegment<T>(array);
+
#region IList<T>
T IList<T>.this[int index]
{
get
{
- if (_array == null)
- ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NullArray);
+ ThrowInvalidOperationIfDefault();
if (index < 0 || index >= _count)
ThrowHelper.ThrowArgumentOutOfRange_IndexException();
Contract.EndContractBlock();
set
{
- if (_array == null)
- ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NullArray);
+ ThrowInvalidOperationIfDefault();
if (index < 0 || index >= _count)
ThrowHelper.ThrowArgumentOutOfRange_IndexException();
Contract.EndContractBlock();
int IList<T>.IndexOf(T item)
{
- if (_array == null)
- ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NullArray);
- Contract.EndContractBlock();
+ ThrowInvalidOperationIfDefault();
int index = System.Array.IndexOf<T>(_array, item, _offset, _count);
{
get
{
- if (_array == null)
- ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NullArray);
+ ThrowInvalidOperationIfDefault();
if (index < 0 || index >= _count)
ThrowHelper.ThrowArgumentOutOfRange_IndexException();
Contract.EndContractBlock();
bool ICollection<T>.Contains(T item)
{
- if (_array == null)
- ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NullArray);
- Contract.EndContractBlock();
+ ThrowInvalidOperationIfDefault();
int index = System.Array.IndexOf<T>(_array, item, _offset, _count);
return index >= 0;
}
- void ICollection<T>.CopyTo(T[] array, int arrayIndex)
- {
- if (_array == null)
- ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NullArray);
- Contract.EndContractBlock();
-
- System.Array.Copy(_array, _offset, array, arrayIndex, _count);
- }
-
bool ICollection<T>.Remove(T item)
{
ThrowHelper.ThrowNotSupportedException();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
#endregion
+ private void ThrowInvalidOperationIfDefault()
+ {
+ if (_array == null)
+ {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NullArray);
+ }
+ }
+
[Serializable]
public struct Enumerator : IEnumerator<T>
{