aboutsummaryrefslogtreecommitdiff
path: root/csharp/src/ProtocolBuffers/Collections/RepeatedField.cs
diff options
context:
space:
mode:
Diffstat (limited to 'csharp/src/ProtocolBuffers/Collections/RepeatedField.cs')
-rw-r--r--csharp/src/ProtocolBuffers/Collections/RepeatedField.cs168
1 files changed, 168 insertions, 0 deletions
diff --git a/csharp/src/ProtocolBuffers/Collections/RepeatedField.cs b/csharp/src/ProtocolBuffers/Collections/RepeatedField.cs
new file mode 100644
index 00000000..7dcd060e
--- /dev/null
+++ b/csharp/src/ProtocolBuffers/Collections/RepeatedField.cs
@@ -0,0 +1,168 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace Google.Protobuf.Collections
+{
+ public sealed class RepeatedField<T> : IList<T>, IEquatable<RepeatedField<T>>
+ {
+ private readonly List<T> list = new List<T>();
+
+ public void Add(T item)
+ {
+ if (item == null)
+ {
+ throw new ArgumentNullException("item");
+ }
+ list.Add(item);
+ }
+
+ public void Clear()
+ {
+ list.Clear();
+ }
+
+ public bool Contains(T item)
+ {
+ if (item == null)
+ {
+ throw new ArgumentNullException("item");
+ }
+ return list.Contains(item);
+ }
+
+ public void CopyTo(T[] array, int arrayIndex)
+ {
+ list.CopyTo(array);
+ }
+
+ public bool Remove(T item)
+ {
+ if (item == null)
+ {
+ throw new ArgumentNullException("item");
+ }
+ return list.Remove(item);
+ }
+
+ public int Count { get { return list.Count; } }
+
+ // TODO(jonskeet): If we implement freezing, make this reflect it.
+ public bool IsReadOnly { get { return false; } }
+
+ public void Add(RepeatedField<T> values)
+ {
+ if (values == null)
+ {
+ throw new ArgumentNullException("values");
+ }
+ // We know that all the values will be valid, because it's a RepeatedField.
+ list.AddRange(values);
+ }
+
+ public void Add(IEnumerable<T> values)
+ {
+ if (values == null)
+ {
+ throw new ArgumentNullException("values");
+ }
+ foreach (T item in values)
+ {
+ Add(item);
+ }
+ }
+
+ // TODO(jonskeet): Create our own mutable struct for this, rather than relying on List<T>.
+ public List<T>.Enumerator GetEnumerator()
+ {
+ return list.GetEnumerator();
+ }
+
+ IEnumerator<T> IEnumerable<T>.GetEnumerator()
+ {
+ return list.GetEnumerator();
+ }
+
+ public override bool Equals(object obj)
+ {
+ return Equals(obj as RepeatedField<T>);
+ }
+
+ public override int GetHashCode()
+ {
+ int hash = 23;
+ foreach (T item in this)
+ {
+ hash = hash * 31 + item.GetHashCode();
+ }
+ return hash;
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+
+ public bool Equals(RepeatedField<T> other)
+ {
+ if (ReferenceEquals(other, null))
+ {
+ return false;
+ }
+ if (ReferenceEquals(other, this))
+ {
+ return true;
+ }
+ if (other.Count != this.Count)
+ {
+ return false;
+ }
+ // TODO(jonskeet): Does this box for enums?
+ EqualityComparer<T> comparer = EqualityComparer<T>.Default;
+ for (int i = 0; i < Count; i++)
+ {
+ if (!comparer.Equals(this[i], other[i]))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public int IndexOf(T item)
+ {
+ if (item == null)
+ {
+ throw new ArgumentNullException("item");
+ }
+ return list.IndexOf(item);
+ }
+
+ public void Insert(int index, T item)
+ {
+ if (item == null)
+ {
+ throw new ArgumentNullException("item");
+ }
+ list.Insert(index, item);
+ }
+
+ public void RemoveAt(int index)
+ {
+ list.RemoveAt(index);
+ }
+
+ public T this[int index]
+ {
+ get { return list[index]; }
+ set
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException("value");
+ }
+ list[index] = value;
+ }
+ }
+ }
+}