| OLD | NEW |
| 1 #region Copyright notice and license | 1 #region Copyright notice and license |
| 2 // Protocol Buffers - Google's data interchange format | 2 // Protocol Buffers - Google's data interchange format |
| 3 // Copyright 2015 Google Inc. All rights reserved. | 3 // Copyright 2015 Google Inc. All rights reserved. |
| 4 // https://developers.google.com/protocol-buffers/ | 4 // https://developers.google.com/protocol-buffers/ |
| 5 // | 5 // |
| 6 // Redistribution and use in source and binary forms, with or without | 6 // Redistribution and use in source and binary forms, with or without |
| 7 // modification, are permitted provided that the following conditions are | 7 // modification, are permitted provided that the following conditions are |
| 8 // met: | 8 // met: |
| 9 // | 9 // |
| 10 // * Redistributions of source code must retain the above copyright | 10 // * Redistributions of source code must retain the above copyright |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 23 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 24 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 24 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 25 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 25 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 26 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 26 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 27 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 27 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 28 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 28 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 29 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 29 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 30 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 30 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 31 #endregion | 31 #endregion |
| 32 | 32 |
| 33 using Google.Protobuf.Compatibility; |
| 33 using Google.Protobuf.Reflection; | 34 using Google.Protobuf.Reflection; |
| 34 using System; | 35 using System; |
| 35 using System.Collections; | 36 using System.Collections; |
| 36 using System.Collections.Generic; | 37 using System.Collections.Generic; |
| 37 using System.IO; | 38 using System.IO; |
| 38 using System.Linq; | 39 using System.Linq; |
| 39 using System.Text; | |
| 40 using Google.Protobuf.Compatibility; | |
| 41 | 40 |
| 42 namespace Google.Protobuf.Collections | 41 namespace Google.Protobuf.Collections |
| 43 { | 42 { |
| 44 /// <summary> | 43 /// <summary> |
| 45 /// Representation of a map field in a Protocol Buffer message. | 44 /// Representation of a map field in a Protocol Buffer message. |
| 46 /// </summary> | 45 /// </summary> |
| 47 /// <typeparam name="TKey">Key type in the map. Must be a type supported by
Protocol Buffer map keys.</typeparam> | 46 /// <typeparam name="TKey">Key type in the map. Must be a type supported by
Protocol Buffer map keys.</typeparam> |
| 48 /// <typeparam name="TValue">Value type in the map. Must be a type supported
by Protocol Buffers.</typeparam> | 47 /// <typeparam name="TValue">Value type in the map. Must be a type supported
by Protocol Buffers.</typeparam> |
| 49 /// <remarks> | 48 /// <remarks> |
| 50 /// <para> | 49 /// <para> |
| 51 /// This implementation preserves insertion order for simplicity of testing | |
| 52 /// code using maps fields. Overwriting an existing entry does not change th
e | |
| 53 /// position of that entry within the map. Equality is not order-sensitive. | |
| 54 /// For string keys, the equality comparison is provided by <see cref="Strin
gComparer.Ordinal" />. | 50 /// For string keys, the equality comparison is provided by <see cref="Strin
gComparer.Ordinal" />. |
| 55 /// </para> | 51 /// </para> |
| 56 /// <para> | 52 /// <para> |
| 57 /// Null values are not permitted in the map, either for wrapper types or re
gular messages. | 53 /// Null values are not permitted in the map, either for wrapper types or re
gular messages. |
| 58 /// If a map is deserialized from a data stream and the value is missing fro
m an entry, a default value | 54 /// If a map is deserialized from a data stream and the value is missing fro
m an entry, a default value |
| 59 /// is created instead. For primitive types, that is the regular default val
ue (0, the empty string and so | 55 /// is created instead. For primitive types, that is the regular default val
ue (0, the empty string and so |
| 60 /// on); for message types, an empty instance of the message is created, as
if the map entry contained a 0-length | 56 /// on); for message types, an empty instance of the message is created, as
if the map entry contained a 0-length |
| 61 /// encoded value for the field. | 57 /// encoded value for the field. |
| 62 /// </para> | 58 /// </para> |
| 63 /// <para> | 59 /// <para> |
| 64 /// This implementation does not generally prohibit the use of key/value typ
es which are not | 60 /// This implementation does not generally prohibit the use of key/value typ
es which are not |
| 65 /// supported by Protocol Buffers (e.g. using a key type of <code>byte</code
>) but nor does it guarantee | 61 /// supported by Protocol Buffers (e.g. using a key type of <code>byte</code
>) but nor does it guarantee |
| 66 /// that all operations will work in such cases. | 62 /// that all operations will work in such cases. |
| 67 /// </para> | 63 /// </para> |
| 64 /// <para> |
| 65 /// The order in which entries are returned when iterating over this object
is undefined, and may change |
| 66 /// in future versions. |
| 67 /// </para> |
| 68 /// </remarks> | 68 /// </remarks> |
| 69 public sealed class MapField<TKey, TValue> : IDeepCloneable<MapField<TKey, T
Value>>, IDictionary<TKey, TValue>, IEquatable<MapField<TKey, TValue>>, IDiction
ary | 69 public sealed class MapField<TKey, TValue> : IDeepCloneable<MapField<TKey, T
Value>>, IDictionary<TKey, TValue>, IEquatable<MapField<TKey, TValue>>, IDiction
ary |
| 70 { | 70 { |
| 71 // TODO: Don't create the map/list until we have an entry. (Assume many
maps will be empty.) | 71 // TODO: Don't create the map/list until we have an entry. (Assume many
maps will be empty.) |
| 72 private readonly Dictionary<TKey, LinkedListNode<KeyValuePair<TKey, TVal
ue>>> map = | 72 private readonly Dictionary<TKey, LinkedListNode<KeyValuePair<TKey, TVal
ue>>> map = |
| 73 new Dictionary<TKey, LinkedListNode<KeyValuePair<TKey, TValue>>>(); | 73 new Dictionary<TKey, LinkedListNode<KeyValuePair<TKey, TValue>>>(); |
| 74 private readonly LinkedList<KeyValuePair<TKey, TValue>> list = new Linke
dList<KeyValuePair<TKey, TValue>>(); | 74 private readonly LinkedList<KeyValuePair<TKey, TValue>> list = new Linke
dList<KeyValuePair<TKey, TValue>>(); |
| 75 | 75 |
| 76 /// <summary> | 76 /// <summary> |
| 77 /// Creates a deep clone of this object. | 77 /// Creates a deep clone of this object. |
| (...skipping 27 matching lines...) Expand all Loading... |
| 105 /// This operation fails if the key already exists in the map. To replac
e an existing entry, use the indexer. | 105 /// This operation fails if the key already exists in the map. To replac
e an existing entry, use the indexer. |
| 106 /// </remarks> | 106 /// </remarks> |
| 107 /// <param name="key">The key to add</param> | 107 /// <param name="key">The key to add</param> |
| 108 /// <param name="value">The value to add.</param> | 108 /// <param name="value">The value to add.</param> |
| 109 /// <exception cref="System.ArgumentException">The given key already exi
sts in map.</exception> | 109 /// <exception cref="System.ArgumentException">The given key already exi
sts in map.</exception> |
| 110 public void Add(TKey key, TValue value) | 110 public void Add(TKey key, TValue value) |
| 111 { | 111 { |
| 112 // Validation of arguments happens in ContainsKey and the indexer | 112 // Validation of arguments happens in ContainsKey and the indexer |
| 113 if (ContainsKey(key)) | 113 if (ContainsKey(key)) |
| 114 { | 114 { |
| 115 throw new ArgumentException("Key already exists in map", "key"); | 115 throw new ArgumentException("Key already exists in map", nameof(
key)); |
| 116 } | 116 } |
| 117 this[key] = value; | 117 this[key] = value; |
| 118 } | 118 } |
| 119 | 119 |
| 120 /// <summary> | 120 /// <summary> |
| 121 /// Determines whether the specified key is present in the map. | 121 /// Determines whether the specified key is present in the map. |
| 122 /// </summary> | 122 /// </summary> |
| 123 /// <param name="key">The key to check.</param> | 123 /// <param name="key">The key to check.</param> |
| 124 /// <returns><c>true</c> if the map contains the given key; <c>false</c>
otherwise.</returns> | 124 /// <returns><c>true</c> if the map contains the given key; <c>false</c>
otherwise.</returns> |
| 125 public bool ContainsKey(TKey key) | 125 public bool ContainsKey(TKey key) |
| 126 { | 126 { |
| 127 ProtoPreconditions.CheckNotNullUnconstrained(key, "key"); | 127 ProtoPreconditions.CheckNotNullUnconstrained(key, nameof(key)); |
| 128 return map.ContainsKey(key); | 128 return map.ContainsKey(key); |
| 129 } | 129 } |
| 130 | 130 |
| 131 private bool ContainsValue(TValue value) | 131 private bool ContainsValue(TValue value) |
| 132 { | 132 { |
| 133 var comparer = EqualityComparer<TValue>.Default; | 133 var comparer = EqualityComparer<TValue>.Default; |
| 134 return list.Any(pair => comparer.Equals(pair.Value, value)); | 134 return list.Any(pair => comparer.Equals(pair.Value, value)); |
| 135 } | 135 } |
| 136 | 136 |
| 137 /// <summary> | 137 /// <summary> |
| 138 /// Removes the entry identified by the given key from the map. | 138 /// Removes the entry identified by the given key from the map. |
| 139 /// </summary> | 139 /// </summary> |
| 140 /// <param name="key">The key indicating the entry to remove from the ma
p.</param> | 140 /// <param name="key">The key indicating the entry to remove from the ma
p.</param> |
| 141 /// <returns><c>true</c> if the map contained the given key before the e
ntry was removed; <c>false</c> otherwise.</returns> | 141 /// <returns><c>true</c> if the map contained the given key before the e
ntry was removed; <c>false</c> otherwise.</returns> |
| 142 public bool Remove(TKey key) | 142 public bool Remove(TKey key) |
| 143 { | 143 { |
| 144 ProtoPreconditions.CheckNotNullUnconstrained(key, "key"); | 144 ProtoPreconditions.CheckNotNullUnconstrained(key, nameof(key)); |
| 145 LinkedListNode<KeyValuePair<TKey, TValue>> node; | 145 LinkedListNode<KeyValuePair<TKey, TValue>> node; |
| 146 if (map.TryGetValue(key, out node)) | 146 if (map.TryGetValue(key, out node)) |
| 147 { | 147 { |
| 148 map.Remove(key); | 148 map.Remove(key); |
| 149 node.List.Remove(node); | 149 node.List.Remove(node); |
| 150 return true; | 150 return true; |
| 151 } | 151 } |
| 152 else | 152 else |
| 153 { | 153 { |
| 154 return false; | 154 return false; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 182 /// Gets or sets the value associated with the specified key. | 182 /// Gets or sets the value associated with the specified key. |
| 183 /// </summary> | 183 /// </summary> |
| 184 /// <param name="key">The key of the value to get or set.</param> | 184 /// <param name="key">The key of the value to get or set.</param> |
| 185 /// <exception cref="KeyNotFoundException">The property is retrieved and
key does not exist in the collection.</exception> | 185 /// <exception cref="KeyNotFoundException">The property is retrieved and
key does not exist in the collection.</exception> |
| 186 /// <returns>The value associated with the specified key. If the specifi
ed key is not found, | 186 /// <returns>The value associated with the specified key. If the specifi
ed key is not found, |
| 187 /// a get operation throws a <see cref="KeyNotFoundException"/>, and a s
et operation creates a new element with the specified key.</returns> | 187 /// a get operation throws a <see cref="KeyNotFoundException"/>, and a s
et operation creates a new element with the specified key.</returns> |
| 188 public TValue this[TKey key] | 188 public TValue this[TKey key] |
| 189 { | 189 { |
| 190 get | 190 get |
| 191 { | 191 { |
| 192 ProtoPreconditions.CheckNotNullUnconstrained(key, "key"); | 192 ProtoPreconditions.CheckNotNullUnconstrained(key, nameof(key)); |
| 193 TValue value; | 193 TValue value; |
| 194 if (TryGetValue(key, out value)) | 194 if (TryGetValue(key, out value)) |
| 195 { | 195 { |
| 196 return value; | 196 return value; |
| 197 } | 197 } |
| 198 throw new KeyNotFoundException(); | 198 throw new KeyNotFoundException(); |
| 199 } | 199 } |
| 200 set | 200 set |
| 201 { | 201 { |
| 202 ProtoPreconditions.CheckNotNullUnconstrained(key, "key"); | 202 ProtoPreconditions.CheckNotNullUnconstrained(key, nameof(key)); |
| 203 // value == null check here is redundant, but avoids boxing. | 203 // value == null check here is redundant, but avoids boxing. |
| 204 if (value == null) | 204 if (value == null) |
| 205 { | 205 { |
| 206 ProtoPreconditions.CheckNotNullUnconstrained(value, "value")
; | 206 ProtoPreconditions.CheckNotNullUnconstrained(value, nameof(v
alue)); |
| 207 } | 207 } |
| 208 LinkedListNode<KeyValuePair<TKey, TValue>> node; | 208 LinkedListNode<KeyValuePair<TKey, TValue>> node; |
| 209 var pair = new KeyValuePair<TKey, TValue>(key, value); | 209 var pair = new KeyValuePair<TKey, TValue>(key, value); |
| 210 if (map.TryGetValue(key, out node)) | 210 if (map.TryGetValue(key, out node)) |
| 211 { | 211 { |
| 212 node.Value = pair; | 212 node.Value = pair; |
| 213 } | 213 } |
| 214 else | 214 else |
| 215 { | 215 { |
| 216 node = list.AddLast(pair); | 216 node = list.AddLast(pair); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 228 /// Gets a collection containing the values in the map. | 228 /// Gets a collection containing the values in the map. |
| 229 /// </summary> | 229 /// </summary> |
| 230 public ICollection<TValue> Values { get { return new MapView<TValue>(thi
s, pair => pair.Value, ContainsValue); } } | 230 public ICollection<TValue> Values { get { return new MapView<TValue>(thi
s, pair => pair.Value, ContainsValue); } } |
| 231 | 231 |
| 232 /// <summary> | 232 /// <summary> |
| 233 /// Adds the specified entries to the map. The keys and values are not a
utomatically cloned. | 233 /// Adds the specified entries to the map. The keys and values are not a
utomatically cloned. |
| 234 /// </summary> | 234 /// </summary> |
| 235 /// <param name="entries">The entries to add to the map.</param> | 235 /// <param name="entries">The entries to add to the map.</param> |
| 236 public void Add(IDictionary<TKey, TValue> entries) | 236 public void Add(IDictionary<TKey, TValue> entries) |
| 237 { | 237 { |
| 238 ProtoPreconditions.CheckNotNull(entries, "entries"); | 238 ProtoPreconditions.CheckNotNull(entries, nameof(entries)); |
| 239 foreach (var pair in entries) | 239 foreach (var pair in entries) |
| 240 { | 240 { |
| 241 Add(pair.Key, pair.Value); | 241 Add(pair.Key, pair.Value); |
| 242 } | 242 } |
| 243 } | 243 } |
| 244 | 244 |
| 245 /// <summary> | 245 /// <summary> |
| 246 /// Returns an enumerator that iterates through the collection. | 246 /// Returns an enumerator that iterates through the collection. |
| 247 /// </summary> | 247 /// </summary> |
| 248 /// <returns> | 248 /// <returns> |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 307 /// <summary> | 307 /// <summary> |
| 308 /// Removes the specified key/value pair from the map. | 308 /// Removes the specified key/value pair from the map. |
| 309 /// </summary> | 309 /// </summary> |
| 310 /// <remarks>Both the key and the value must be found for the entry to b
e removed.</remarks> | 310 /// <remarks>Both the key and the value must be found for the entry to b
e removed.</remarks> |
| 311 /// <param name="item">The key/value pair to remove.</param> | 311 /// <param name="item">The key/value pair to remove.</param> |
| 312 /// <returns><c>true</c> if the key/value pair was found and removed; <c
>false</c> otherwise.</returns> | 312 /// <returns><c>true</c> if the key/value pair was found and removed; <c
>false</c> otherwise.</returns> |
| 313 bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, T
Value> item) | 313 bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, T
Value> item) |
| 314 { | 314 { |
| 315 if (item.Key == null) | 315 if (item.Key == null) |
| 316 { | 316 { |
| 317 throw new ArgumentException("Key is null", "item"); | 317 throw new ArgumentException("Key is null", nameof(item)); |
| 318 } | 318 } |
| 319 LinkedListNode<KeyValuePair<TKey, TValue>> node; | 319 LinkedListNode<KeyValuePair<TKey, TValue>> node; |
| 320 if (map.TryGetValue(item.Key, out node) && | 320 if (map.TryGetValue(item.Key, out node) && |
| 321 EqualityComparer<TValue>.Default.Equals(item.Value, node.Value.V
alue)) | 321 EqualityComparer<TValue>.Default.Equals(item.Value, node.Value.V
alue)) |
| 322 { | 322 { |
| 323 map.Remove(item.Key); | 323 map.Remove(item.Key); |
| 324 node.List.Remove(node); | 324 node.List.Remove(node); |
| 325 return true; | 325 return true; |
| 326 } | 326 } |
| 327 else | 327 else |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 495 return ContainsKey((TKey)key); | 495 return ContainsKey((TKey)key); |
| 496 } | 496 } |
| 497 | 497 |
| 498 IDictionaryEnumerator IDictionary.GetEnumerator() | 498 IDictionaryEnumerator IDictionary.GetEnumerator() |
| 499 { | 499 { |
| 500 return new DictionaryEnumerator(GetEnumerator()); | 500 return new DictionaryEnumerator(GetEnumerator()); |
| 501 } | 501 } |
| 502 | 502 |
| 503 void IDictionary.Remove(object key) | 503 void IDictionary.Remove(object key) |
| 504 { | 504 { |
| 505 ProtoPreconditions.CheckNotNull(key, "key"); | 505 ProtoPreconditions.CheckNotNull(key, nameof(key)); |
| 506 if (!(key is TKey)) | 506 if (!(key is TKey)) |
| 507 { | 507 { |
| 508 return; | 508 return; |
| 509 } | 509 } |
| 510 Remove((TKey)key); | 510 Remove((TKey)key); |
| 511 } | 511 } |
| 512 | 512 |
| 513 void ICollection.CopyTo(Array array, int index) | 513 void ICollection.CopyTo(Array array, int index) |
| 514 { | 514 { |
| 515 // This is ugly and slow as heck, but with any luck it will never be
used anyway. | 515 // This is ugly and slow as heck, but with any luck it will never be
used anyway. |
| 516 ICollection temp = this.Select(pair => new DictionaryEntry(pair.Key,
pair.Value)).ToList(); | 516 ICollection temp = this.Select(pair => new DictionaryEntry(pair.Key,
pair.Value)).ToList(); |
| 517 temp.CopyTo(array, index); | 517 temp.CopyTo(array, index); |
| 518 } | 518 } |
| 519 | 519 |
| 520 bool IDictionary.IsFixedSize { get { return false; } } | 520 bool IDictionary.IsFixedSize { get { return false; } } |
| 521 | 521 |
| 522 ICollection IDictionary.Keys { get { return (ICollection)Keys; } } | 522 ICollection IDictionary.Keys { get { return (ICollection)Keys; } } |
| 523 | 523 |
| 524 ICollection IDictionary.Values { get { return (ICollection)Values; } } | 524 ICollection IDictionary.Values { get { return (ICollection)Values; } } |
| 525 | 525 |
| 526 bool ICollection.IsSynchronized { get { return false; } } | 526 bool ICollection.IsSynchronized { get { return false; } } |
| 527 | 527 |
| 528 object ICollection.SyncRoot { get { return this; } } | 528 object ICollection.SyncRoot { get { return this; } } |
| 529 | 529 |
| 530 object IDictionary.this[object key] | 530 object IDictionary.this[object key] |
| 531 { | 531 { |
| 532 get | 532 get |
| 533 { | 533 { |
| 534 ProtoPreconditions.CheckNotNull(key, "key"); | 534 ProtoPreconditions.CheckNotNull(key, nameof(key)); |
| 535 if (!(key is TKey)) | 535 if (!(key is TKey)) |
| 536 { | 536 { |
| 537 return null; | 537 return null; |
| 538 } | 538 } |
| 539 TValue value; | 539 TValue value; |
| 540 TryGetValue((TKey)key, out value); | 540 TryGetValue((TKey)key, out value); |
| 541 return value; | 541 return value; |
| 542 } | 542 } |
| 543 | 543 |
| 544 set | 544 set |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 706 | 706 |
| 707 public bool Contains(T item) | 707 public bool Contains(T item) |
| 708 { | 708 { |
| 709 return containsCheck(item); | 709 return containsCheck(item); |
| 710 } | 710 } |
| 711 | 711 |
| 712 public void CopyTo(T[] array, int arrayIndex) | 712 public void CopyTo(T[] array, int arrayIndex) |
| 713 { | 713 { |
| 714 if (arrayIndex < 0) | 714 if (arrayIndex < 0) |
| 715 { | 715 { |
| 716 throw new ArgumentOutOfRangeException("arrayIndex"); | 716 throw new ArgumentOutOfRangeException(nameof(arrayIndex)); |
| 717 } | 717 } |
| 718 if (arrayIndex + Count >= array.Length) | 718 if (arrayIndex + Count >= array.Length) |
| 719 { | 719 { |
| 720 throw new ArgumentException("Not enough space in the array",
"array"); | 720 throw new ArgumentException("Not enough space in the array",
nameof(array)); |
| 721 } | 721 } |
| 722 foreach (var item in this) | 722 foreach (var item in this) |
| 723 { | 723 { |
| 724 array[arrayIndex++] = item; | 724 array[arrayIndex++] = item; |
| 725 } | 725 } |
| 726 } | 726 } |
| 727 | 727 |
| 728 public IEnumerator<T> GetEnumerator() | 728 public IEnumerator<T> GetEnumerator() |
| 729 { | 729 { |
| 730 return parent.list.Select(projection).GetEnumerator(); | 730 return parent.list.Select(projection).GetEnumerator(); |
| 731 } | 731 } |
| 732 | 732 |
| 733 public bool Remove(T item) | 733 public bool Remove(T item) |
| 734 { | 734 { |
| 735 throw new NotSupportedException(); | 735 throw new NotSupportedException(); |
| 736 } | 736 } |
| 737 | 737 |
| 738 IEnumerator IEnumerable.GetEnumerator() | 738 IEnumerator IEnumerable.GetEnumerator() |
| 739 { | 739 { |
| 740 return GetEnumerator(); | 740 return GetEnumerator(); |
| 741 } | 741 } |
| 742 | 742 |
| 743 public void CopyTo(Array array, int index) | 743 public void CopyTo(Array array, int index) |
| 744 { | 744 { |
| 745 if (index < 0) | 745 if (index < 0) |
| 746 { | 746 { |
| 747 throw new ArgumentOutOfRangeException("index"); | 747 throw new ArgumentOutOfRangeException(nameof(index)); |
| 748 } | 748 } |
| 749 if (index + Count >= array.Length) | 749 if (index + Count >= array.Length) |
| 750 { | 750 { |
| 751 throw new ArgumentException("Not enough space in the array",
"array"); | 751 throw new ArgumentException("Not enough space in the array",
nameof(array)); |
| 752 } | 752 } |
| 753 foreach (var item in this) | 753 foreach (var item in this) |
| 754 { | 754 { |
| 755 array.SetValue(item, index++); | 755 array.SetValue(item, index++); |
| 756 } | 756 } |
| 757 } | 757 } |
| 758 } | 758 } |
| 759 } | 759 } |
| 760 } | 760 } |
| OLD | NEW |