aboutsummaryrefslogtreecommitdiffhomepage
path: root/csharp/src/Google.Protobuf/Collections
diff options
context:
space:
mode:
authorGravatar Jon Skeet <jonskeet@google.com>2015-08-08 07:17:58 +0100
committerGravatar Jon Skeet <jonskeet@google.com>2015-08-08 08:59:53 +0100
commit3f45d7c11e200184cfc09fb92efe25a63df1eef1 (patch)
treec69a46147733f1bde5d70ecbf2c49f86e8924ee3 /csharp/src/Google.Protobuf/Collections
parente58cdbd2146bc8e2e2f5bf4bc8a7576f82535ae6 (diff)
Implement Keys and Values as views
Diffstat (limited to 'csharp/src/Google.Protobuf/Collections')
-rw-r--r--csharp/src/Google.Protobuf/Collections/MapField.cs88
1 files changed, 84 insertions, 4 deletions
diff --git a/csharp/src/Google.Protobuf/Collections/MapField.cs b/csharp/src/Google.Protobuf/Collections/MapField.cs
index dc4b04cb..6dcdc100 100644
--- a/csharp/src/Google.Protobuf/Collections/MapField.cs
+++ b/csharp/src/Google.Protobuf/Collections/MapField.cs
@@ -136,6 +136,12 @@ namespace Google.Protobuf.Collections
return map.ContainsKey(key);
}
+ private bool ContainsValue(TValue value)
+ {
+ var comparer = EqualityComparer<TValue>.Default;
+ return list.Any(pair => comparer.Equals(pair.Value, value));
+ }
+
/// <summary>
/// Removes the entry identified by the given key from the map.
/// </summary>
@@ -221,17 +227,15 @@ namespace Google.Protobuf.Collections
}
}
- // TODO: Make these views?
-
/// <summary>
/// Gets a collection containing the keys in the map.
/// </summary>
- public ICollection<TKey> Keys { get { return list.Select(t => t.Key).ToList(); } }
+ public ICollection<TKey> Keys { get { return new MapView<TKey>(this, pair => pair.Key, ContainsKey); } }
/// <summary>
/// Gets a collection containing the values in the map.
/// </summary>
- public ICollection<TValue> Values { get { return list.Select(t => t.Value).ToList(); } }
+ public ICollection<TValue> Values { get { return new MapView<TValue>(this, pair => pair.Value, ContainsValue); } }
/// <summary>
/// Adds the specified entries to the map.
@@ -658,5 +662,81 @@ namespace Google.Protobuf.Collections
MessageDescriptor IMessage.Descriptor { get { return null; } }
}
}
+
+ private class MapView<T> : ICollection<T>, ICollection
+ {
+ private readonly MapField<TKey, TValue> parent;
+ private readonly Func<KeyValuePair<TKey, TValue>, T> projection;
+ private readonly Func<T, bool> containsCheck;
+
+ internal MapView(
+ MapField<TKey, TValue> parent,
+ Func<KeyValuePair<TKey, TValue>, T> projection,
+ Func<T, bool> containsCheck)
+ {
+ this.parent = parent;
+ this.projection = projection;
+ this.containsCheck = containsCheck;
+ }
+
+ public int Count { get { return parent.Count; } }
+
+ public bool IsReadOnly { get { return true; } }
+
+ public bool IsSynchronized { get { return false; } }
+
+ public object SyncRoot { get { return parent; } }
+
+ public void Add(T item)
+ {
+ throw new NotSupportedException();
+ }
+
+ public void Clear()
+ {
+ throw new NotSupportedException();
+ }
+
+ public bool Contains(T item)
+ {
+ return containsCheck(item);
+ }
+
+ public void CopyTo(T[] array, int arrayIndex)
+ {
+ if (arrayIndex < 0)
+ {
+ throw new ArgumentOutOfRangeException("arrayIndex");
+ }
+ if (arrayIndex + Count >= array.Length)
+ {
+ throw new ArgumentException("Not enough space in the array", "array");
+ }
+ foreach (var item in this)
+ {
+ array[arrayIndex++] = item;
+ }
+ }
+
+ public IEnumerator<T> GetEnumerator()
+ {
+ return parent.list.Select(projection).GetEnumerator();
+ }
+
+ public bool Remove(T item)
+ {
+ throw new NotSupportedException();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+
+ public void CopyTo(Array array, int index)
+ {
+ throw new NotImplementedException();
+ }
+ }
}
}