/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Microsoft Public License. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Microsoft Public License, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Microsoft Public License.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Dynamic.Utils;
using System.Linq.Expressions;
#if SILVERLIGHT
using System.Core;
#endif
namespace System.Runtime.CompilerServices {
///
/// The builder for read only collection.
///
/// The type of the collection element.
#if !SILVERLIGHT
[Serializable]
#endif
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix")]
public sealed class ReadOnlyCollectionBuilder : IList, System.Collections.IList {
private const int DefaultCapacity = 4;
private T[] _items;
private int _size;
private int _version;
#if !SILVERLIGHT
[NonSerialized]
#endif
private Object _syncRoot;
static readonly T[] _emptyArray = new T[0];
///
/// Constructs a ReadOnlyCollectionBuilder.
///
public ReadOnlyCollectionBuilder() {
_items = _emptyArray;
}
///
/// Constructs a ReadOnlyCollectionBuilder with a given initial capacity.
/// The contents are empty but builder will have reserved room for the given
/// number of elements before any reallocations are required.
///
public ReadOnlyCollectionBuilder(int capacity) {
ContractUtils.Requires(capacity >= 0, "capacity");
_items = new T[capacity];
}
///
/// Constructs a ReadOnlyCollectionBuilder, copying contents of the given collection.
///
///
public ReadOnlyCollectionBuilder(IEnumerable collection) {
ContractUtils.Requires(collection != null, "collection");
ICollection c = collection as ICollection;
if (c != null) {
int count = c.Count;
_items = new T[count];
c.CopyTo(_items, 0);
_size = count;
} else {
_size = 0;
_items = new T[DefaultCapacity];
using (IEnumerator en = collection.GetEnumerator()) {
while (en.MoveNext()) {
Add(en.Current);
}
}
}
}
///
/// Gets and sets the capacity of this ReadOnlyCollectionBuilder
///
public int Capacity {
get { return _items.Length; }
set {
ContractUtils.Requires(value >= _size, "value");
if (value != _items.Length) {
if (value > 0) {
T[] newItems = new T[value];
if (_size > 0) {
Array.Copy(_items, 0, newItems, 0, _size);
}
_items = newItems;
} else {
_items = _emptyArray;
}
}
}
}
///
/// Returns number of elements in the ReadOnlyCollectionBuilder.
///
public int Count {
get { return _size; }
}
#region IList Members
///
/// Returns the index of the first occurrence of a given value in the builder.
///
/// An item to search for.
/// The index of the first occurrence of an item.
public int IndexOf(T item) {
return Array.IndexOf(_items, item, 0, _size);
}
///
/// Inserts an item to the at the specified index.
///
/// The zero-based index at which item should be inserted.
/// The object to insert into the .
public void Insert(int index, T item) {
ContractUtils.Requires(index <= _size, "index");
if (_size == _items.Length) {
EnsureCapacity(_size + 1);
}
if (index < _size) {
Array.Copy(_items, index, _items, index + 1, _size - index);
}
_items[index] = item;
_size++;
_version++;
}
///
/// Removes the item at the specified index.
///
/// The zero-based index of the item to remove.
public void RemoveAt(int index) {
ContractUtils.Requires(index >= 0 && index < _size, "index");
_size--;
if (index < _size) {
Array.Copy(_items, index + 1, _items, index, _size - index);
}
_items[_size] = default(T);
_version++;
}
///
/// Gets or sets the element at the specified index.
///
/// The zero-based index of the element to get or set.
/// The element at the specified index.
public T this[int index] {
get {
ContractUtils.Requires(index < _size, "index");
return _items[index];
}
set {
ContractUtils.Requires(index < _size, "index");
_items[index] = value;
_version++;
}
}
#endregion
#region ICollection Members
///
/// Adds an item to the .
///
/// The object to add to the .
public void Add(T item) {
if (_size == _items.Length) {
EnsureCapacity(_size + 1);
}
_items[_size++] = item;
_version++;
}
///
/// Removes all items from the .
///
public void Clear() {
if (_size > 0) {
Array.Clear(_items, 0, _size);
_size = 0;
}
_version++;
}
///
/// Determines whether the contains a specific value
///
/// the object to locate in the .
/// true if item is found in the ; otherwise, false.
public bool Contains(T item) {
if ((Object)item == null) {
for (int i = 0; i < _size; i++) {
if ((Object)_items[i] == null) {
return true;
}
}
return false;
} else {
EqualityComparer c = EqualityComparer.Default;
for (int i = 0; i < _size; i++) {
if (c.Equals(_items[i], item)) {
return true;
}
}
return false;
}
}
///
/// Copies the elements of the to an ,
/// starting at particular index.
///
/// The one-dimensional that is the destination of the elements copied from .
/// The zero-based index in array at which copying begins.
public void CopyTo(T[] array, int arrayIndex) {
Array.Copy(_items, 0, array, arrayIndex, _size);
}
bool ICollection.IsReadOnly {
get { return false; }
}
///
/// Removes the first occurrence of a specific object from the .
///
/// The object to remove from the .
/// true if item was successfully removed from the ;
/// otherwise, false. This method also returns false if item is not found in the original .
///
public bool Remove(T item) {
int index = IndexOf(item);
if (index >= 0) {
RemoveAt(index);
return true;
}
return false;
}
#endregion
#region IEnumerable Members
///
/// Returns an enumerator that iterates through the collection.
///
/// A that can be used to iterate through the collection.
public IEnumerator GetEnumerator() {
return new Enumerator(this);
}
#endregion
#region IEnumerable Members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
return GetEnumerator();
}
#endregion
#region IList Members
bool System.Collections.IList.IsReadOnly {
get { return false; }
}
int System.Collections.IList.Add(object value) {
ValidateNullValue(value, "value");
try {
Add((T)value);
} catch (InvalidCastException) {
ThrowInvalidTypeException(value, "value");
}
return Count - 1;
}
bool System.Collections.IList.Contains(object value) {
if (IsCompatibleObject(value)) {
return Contains((T)value);
} else return false;
}
int System.Collections.IList.IndexOf(object value) {
if (IsCompatibleObject(value)) {
return IndexOf((T)value);
}
return -1;
}
void System.Collections.IList.Insert(int index, object value) {
ValidateNullValue(value, "value");
try {
Insert(index, (T)value);
} catch (InvalidCastException) {
ThrowInvalidTypeException(value, "value");
}
}
bool System.Collections.IList.IsFixedSize {
get { return false; }
}
void System.Collections.IList.Remove(object value) {
if (IsCompatibleObject(value)) {
Remove((T)value);
}
}
object System.Collections.IList.this[int index] {
get {
return this[index];
}
set {
ValidateNullValue(value, "value");
try {
this[index] = (T)value;
} catch (InvalidCastException) {
ThrowInvalidTypeException(value, "value");
}
}
}
#endregion
#region ICollection Members
void System.Collections.ICollection.CopyTo(Array array, int index) {
ContractUtils.RequiresNotNull(array, "array");
ContractUtils.Requires(array.Rank == 1, "array");
Array.Copy(_items, 0, array, index, _size);
}
bool System.Collections.ICollection.IsSynchronized {
get { return false; }
}
object System.Collections.ICollection.SyncRoot {
get {
if (_syncRoot == null) {
System.Threading.Interlocked.CompareExchange