Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
ImmutableDictionary.cs
Go to the documentation of this file.
4using System.Linq;
6
8
9public static class ImmutableDictionary
10{
15
17 {
18 return ImmutableDictionary<TKey, TValue>.Empty.WithComparers(keyComparer);
19 }
20
25
30
35
40
42 {
43 return Create<TKey, TValue>().ToBuilder();
44 }
45
47 {
48 return Create<TKey, TValue>(keyComparer).ToBuilder();
49 }
50
52 {
53 return Create(keyComparer, valueComparer).ToBuilder();
54 }
55
65
71
76
78 {
79 return source.ToImmutableDictionary(keySelector, (TSource v) => v, null, null);
80 }
81
83 {
84 return source.ToImmutableDictionary(keySelector, (TSource v) => v, keyComparer, null);
85 }
86
91
101
103 {
104 return source.ToImmutableDictionary(keyComparer, null);
105 }
106
108 {
109 return source.ToImmutableDictionary(null, null);
110 }
111
113 {
114 Requires.NotNull(map, "map");
115 Requires.NotNullAllowStructs(key, "key");
117 }
118
120 {
121 return dictionary.GetValueOrDefault(key, default(TValue));
122 }
123
125 {
126 Requires.NotNull(dictionary, "dictionary");
127 Requires.NotNullAllowStructs(key, "key");
128 if (dictionary.TryGetValue(key, out TValue value))
129 {
130 return value;
131 }
132 return defaultValue;
133 }
134}
135[DebuggerDisplay("Count = {Count}")]
137public sealed class ImmutableDictionary<TKey, TValue> : IImmutableDictionary<TKey, TValue>, IReadOnlyDictionary<TKey, TValue>, IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable, IReadOnlyCollection<KeyValuePair<TKey, TValue>>, IImmutableDictionaryInternal<TKey, TValue>, IHashKeyCollection<TKey>, IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IDictionary, ICollection where TKey : notnull
138{
139 [DebuggerDisplay("Count = {Count}")]
141 public sealed class Builder : IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable, IReadOnlyDictionary<TKey, TValue>, IReadOnlyCollection<KeyValuePair<TKey, TValue>>, IDictionary, ICollection
142 {
144
146
147 private int _count;
148
150
151 private int _version;
152
153 private object _syncRoot;
154
156 {
157 get
158 {
159 return _comparers.KeyComparer;
160 }
161 set
162 {
163 Requires.NotNull(value, "value");
164 if (value != KeyComparer)
165 {
169 _immutable = null;
171 _count = mutationResult.CountAdjustment;
172 Root = mutationResult.Root;
173 }
174 }
175 }
176
178 {
179 get
180 {
182 }
183 set
184 {
185 Requires.NotNull(value, "value");
186 if (value != ValueComparer)
187 {
189 _immutable = null;
190 }
191 }
192 }
193
194 public int Count => _count;
195
197
199 {
200 get
201 {
203 while (enumerator.MoveNext())
204 {
205 yield return enumerator.Current.Key;
206 }
207 }
208 }
209
211
213 {
214 get
215 {
217 while (enumerator.MoveNext())
218 {
219 yield return enumerator.Current.Value;
220 }
221 }
222 }
223
225
226 bool IDictionary.IsFixedSize => false;
227
228 bool IDictionary.IsReadOnly => false;
229
230 ICollection IDictionary.Keys => Keys.ToArray(Count);
231
232 ICollection IDictionary.Values => Values.ToArray(Count);
233
235 object ICollection.SyncRoot
236 {
237 get
238 {
239 if (_syncRoot == null)
240 {
241 Interlocked.CompareExchange<object>(ref _syncRoot, new object(), (object)null);
242 }
243 return _syncRoot;
244 }
245 }
246
248 bool ICollection.IsSynchronized => false;
249
250 object? IDictionary.this[object key]
251 {
252 get
253 {
254 return this[(TKey)key];
255 }
256 set
257 {
258 this[(TKey)key] = (TValue)value;
259 }
260 }
261
262 internal int Version => _version;
263
265
267 {
268 get
269 {
270 return _root;
271 }
272 set
273 {
274 _version++;
275 if (_root != value)
276 {
277 _root = value;
278 _immutable = null;
279 }
280 }
281 }
282
283 public TValue this[TKey key]
284 {
285 get
286 {
288 {
289 return value;
290 }
292 }
293 set
294 {
296 Apply(result);
297 }
298 }
299
301 {
302 Requires.NotNull(map, "map");
303 _root = map._root;
304 _count = map._count;
305 _comparers = map._comparers;
306 _immutable = map;
307 }
308
309 void IDictionary.Add(object key, object value)
310 {
311 Add((TKey)key, (TValue)value);
312 }
313
315 {
316 return ContainsKey((TKey)key);
317 }
318
323
324 void IDictionary.Remove(object key)
325 {
326 Remove((TKey)key);
327 }
328
330 {
331 Requires.NotNull(array, "array");
332 Requires.Range(arrayIndex >= 0, "arrayIndex");
333 Requires.Range(array.Length >= arrayIndex + Count, "arrayIndex");
335 while (enumerator.MoveNext())
336 {
337 KeyValuePair<TKey, TValue> current = enumerator.Current;
338 array.SetValue(new DictionaryEntry(current.Key, current.Value), arrayIndex++);
339 }
340 }
341
343 {
345 Apply(result);
346 }
347
349 {
350 Requires.NotNull(keys, "keys");
351 foreach (TKey key in keys)
352 {
353 Remove(key);
354 }
355 }
356
358 {
359 return new Enumerator(_root, this);
360 }
361
362 public TValue? GetValueOrDefault(TKey key)
363 {
364 return GetValueOrDefault(key, default(TValue));
365 }
366
367 public TValue GetValueOrDefault(TKey key, TValue defaultValue)
368 {
369 Requires.NotNullAllowStructs(key, "key");
371 {
372 return value;
373 }
374 return defaultValue;
375 }
376
385
386 public void Add(TKey key, TValue value)
387 {
389 Apply(result);
390 }
391
392 public bool ContainsKey(TKey key)
393 {
395 }
396
397 public bool ContainsValue(TValue value)
398 {
400 {
401 while (enumerator.MoveNext())
402 {
403 KeyValuePair<TKey, TValue> current = enumerator.Current;
404 if (ValueComparer.Equals(value, current.Value))
405 {
406 return true;
407 }
408 }
409 }
410 return false;
411 }
412
413 public bool Remove(TKey key)
414 {
416 return Apply(result);
417 }
418
419 public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)
420 {
422 }
423
424 public bool TryGetKey(TKey equalKey, out TKey actualKey)
425 {
427 }
428
430 {
431 Add(item.Key, item.Value);
432 }
433
434 public void Clear()
435 {
437 _count = 0;
438 }
439
444
446 {
447 Requires.NotNull(array, "array");
449 while (enumerator.MoveNext())
450 {
451 KeyValuePair<TKey, TValue> current = enumerator.Current;
452 array[arrayIndex++] = current;
453 }
454 }
455
457 {
458 if (Contains(item))
459 {
460 return Remove(item.Key);
461 }
462 return false;
463 }
464
469
474
475 private bool Apply(MutationResult result)
476 {
477 Root = result.Root;
478 _count += result.CountAdjustment;
479 return result.CountAdjustment != 0;
480 }
481 }
482
483 internal sealed class Comparers : IEqualityComparer<HashBucket>, IEqualityComparer<KeyValuePair<TKey, TValue>>
484 {
486
488
490
492
494
496
498
500 {
501 Requires.NotNull(keyComparer, "keyComparer");
502 Requires.NotNull(valueComparer, "valueComparer");
503 _keyComparer = keyComparer;
505 }
506
507 public bool Equals(HashBucket x, HashBucket y)
508 {
510 {
511 return ValueComparer.Equals(x.FirstValue.Value, y.FirstValue.Value);
512 }
513 return false;
514 }
515
517 {
518 return KeyComparer.GetHashCode(obj.FirstValue.Key);
519 }
520
525
530
532 {
533 Requires.NotNull(keyComparer, "keyComparer");
534 Requires.NotNull(valueComparer, "valueComparer");
535 if (keyComparer != Default.KeyComparer || valueComparer != Default.ValueComparer)
536 {
537 return new Comparers(keyComparer, valueComparer);
538 }
539 return Default;
540 }
541
543 {
544 Requires.NotNull(valueComparer, "valueComparer");
546 {
548 }
549 return this;
550 }
551 }
552
553 public struct Enumerator : IEnumerator<KeyValuePair<TKey, TValue>>, IEnumerator, IDisposable
554 {
555 private readonly Builder _builder;
556
558
560
562
564 {
565 get
566 {
567 _mapEnumerator.ThrowIfDisposed();
568 return _bucketEnumerator.Current;
569 }
570 }
571
572 object IEnumerator.Current => Current;
573
581
582 public bool MoveNext()
583 {
585 if (_bucketEnumerator.MoveNext())
586 {
587 return true;
588 }
589 if (_mapEnumerator.MoveNext())
590 {
592 return _bucketEnumerator.MoveNext();
593 }
594 return false;
595 }
596
597 public void Reset()
598 {
600 _mapEnumerator.Reset();
601 _bucketEnumerator.Dispose();
603 }
604
605 public void Dispose()
606 {
607 _mapEnumerator.Dispose();
608 _bucketEnumerator.Dispose();
609 }
610
618 }
619
620 internal readonly struct HashBucket : IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable
621 {
622 internal struct Enumerator : IEnumerator<KeyValuePair<TKey, TValue>>, IEnumerator, IDisposable
623 {
624 private enum Position
625 {
627 First,
629 End
630 }
631
632 private readonly HashBucket _bucket;
633
635
637
638 object IEnumerator.Current => Current;
639
641 {
642 Position.First => _bucket._firstValue,
643 Position.Additional => _additionalEnumerator.Current,
644 _ => throw new InvalidOperationException(),
645 };
646
647 internal Enumerator(HashBucket bucket)
648 {
649 _bucket = bucket;
650 _currentPosition = Position.BeforeFirst;
652 }
653
654 public bool MoveNext()
655 {
656 if (_bucket.IsEmpty)
657 {
659 return false;
660 }
661 switch (_currentPosition)
662 {
663 case Position.BeforeFirst:
665 return true;
666 case Position.First:
668 {
670 return false;
671 }
672 _currentPosition = Position.Additional;
674 return _additionalEnumerator.MoveNext();
675 case Position.Additional:
676 return _additionalEnumerator.MoveNext();
677 case Position.End:
678 return false;
679 default:
680 throw new InvalidOperationException();
681 }
682 }
683
684 public void Reset()
685 {
686 _additionalEnumerator.Dispose();
687 _currentPosition = Position.BeforeFirst;
688 }
689
690 public void Dispose()
691 {
692 _additionalEnumerator.Dispose();
693 }
694 }
695
697
699
700 internal bool IsEmpty => _additionalElements == null;
701
703 {
704 get
705 {
706 if (IsEmpty)
707 {
708 throw new InvalidOperationException();
709 }
710 return _firstValue;
711 }
712 }
713
715
721
723 {
724 return new Enumerator(this);
725 }
726
731
736
737 public override bool Equals(object? obj)
738 {
739 throw new NotSupportedException();
740 }
741
742 public override int GetHashCode()
743 {
744 throw new NotSupportedException();
745 }
746
748 {
750 if (IsEmpty)
751 {
752 result = OperationResult.SizeChanged;
753 return new HashBucket(keyValuePair);
754 }
756 {
757 switch (behavior)
758 {
759 case KeyCollisionBehavior.SetValue:
760 result = OperationResult.AppliedWithoutSizeChange;
762 case KeyCollisionBehavior.Skip:
763 result = OperationResult.NoChangeRequired;
764 return this;
765 case KeyCollisionBehavior.ThrowIfValueDifferent:
766 if (!valueComparer.Equals(_firstValue.Value, value))
767 {
769 }
770 result = OperationResult.NoChangeRequired;
771 return this;
772 case KeyCollisionBehavior.ThrowAlways:
774 default:
775 throw new InvalidOperationException();
776 }
777 }
779 if (num < 0)
780 {
781 result = OperationResult.SizeChanged;
783 }
784 switch (behavior)
785 {
786 case KeyCollisionBehavior.SetValue:
787 result = OperationResult.AppliedWithoutSizeChange;
788 return new HashBucket(_firstValue, _additionalElements.ReplaceAt(num, keyValuePair));
789 case KeyCollisionBehavior.Skip:
790 result = OperationResult.NoChangeRequired;
791 return this;
792 case KeyCollisionBehavior.ThrowIfValueDifferent:
793 if (!valueComparer.Equals(_additionalElements.ItemRef(num).Value, value))
794 {
796 }
797 result = OperationResult.NoChangeRequired;
798 return this;
799 case KeyCollisionBehavior.ThrowAlways:
801 default:
802 throw new InvalidOperationException();
803 }
804 }
805
807 {
808 if (IsEmpty)
809 {
810 result = OperationResult.NoChangeRequired;
811 return this;
812 }
815 {
817 {
818 result = OperationResult.SizeChanged;
819 return default(HashBucket);
820 }
822 result = OperationResult.SizeChanged;
824 }
826 if (num < 0)
827 {
828 result = OperationResult.NoChangeRequired;
829 return this;
830 }
831 result = OperationResult.SizeChanged;
833 }
834
835 internal bool TryGetValue(TKey key, Comparers comparers, [MaybeNullWhen(false)] out TValue value)
836 {
837 if (IsEmpty)
838 {
839 value = default(TValue);
840 return false;
841 }
842 if (comparers.KeyComparer.Equals(_firstValue.Key, key))
843 {
844 value = _firstValue.Value;
845 return true;
846 }
848 int num = _additionalElements.IndexOf(item, comparers.KeyOnlyComparer);
849 if (num < 0)
850 {
851 value = default(TValue);
852 return false;
853 }
854 value = _additionalElements.ItemRef(num).Value;
855 return true;
856 }
857
859 {
860 if (IsEmpty)
861 {
863 return false;
864 }
865 if (comparers.KeyComparer.Equals(_firstValue.Key, equalKey))
866 {
868 return true;
869 }
871 int num = _additionalElements.IndexOf(item, comparers.KeyOnlyComparer);
872 if (num < 0)
873 {
875 return false;
876 }
878 return true;
879 }
880
881 internal void Freeze()
882 {
883 if (_additionalElements != null)
884 {
885 _additionalElements.Freeze();
886 }
887 }
888 }
889
920
921 private readonly struct MutationResult
922 {
924
925 private readonly int _countAdjustment;
926
928
930
936
938 {
939 Requires.NotNull(root, "root");
940 _root = root;
942 }
943
949 }
950
952 {
953 SetValue,
954 Skip,
957 }
958
965
967
969 {
970 kv.Value.Freeze();
971 };
972
973 private readonly int _count;
974
976
977 private readonly Comparers _comparers;
978
979 public int Count => _count;
980
981 public bool IsEmpty => Count == 0;
982
984
986
988 {
989 get
990 {
992 {
993 foreach (KeyValuePair<TKey, TValue> item2 in item.Value)
994 {
995 yield return item2.Key;
996 }
997 }
998 }
999 }
1000
1002 {
1003 get
1004 {
1006 {
1007 foreach (KeyValuePair<TKey, TValue> item2 in item.Value)
1008 {
1009 yield return item2.Value;
1010 }
1011 }
1012 }
1013 }
1014
1016
1018
1019 private MutationInput Origin => new MutationInput(this);
1020
1021 public TValue this[TKey key]
1022 {
1023 get
1024 {
1025 Requires.NotNullAllowStructs(key, "key");
1026 if (TryGetValue(key, out var value))
1027 {
1028 return value;
1029 }
1031 }
1032 }
1033
1035 {
1036 get
1037 {
1038 return this[key];
1039 }
1040 set
1041 {
1042 throw new NotSupportedException();
1043 }
1044 }
1045
1047
1048 bool IDictionary.IsFixedSize => true;
1049
1050 bool IDictionary.IsReadOnly => true;
1051
1053
1055
1057
1058 object? IDictionary.this[object key]
1059 {
1060 get
1061 {
1062 return this[(TKey)key];
1063 }
1064 set
1065 {
1066 throw new NotSupportedException();
1067 }
1068 }
1069
1071 object ICollection.SyncRoot => this;
1072
1074 bool ICollection.IsSynchronized => true;
1075
1077 : this(Requires.NotNullPassthrough(comparers, "comparers"))
1078 {
1079 Requires.NotNull(root, "root");
1080 root.Freeze(s_FreezeBucketAction);
1081 _root = root;
1082 _count = count;
1083 }
1084
1090
1092 {
1093 if (!IsEmpty)
1094 {
1096 }
1097 return this;
1098 }
1099
1104
1106 {
1107 return new Builder(this);
1108 }
1109
1111 {
1112 Requires.NotNullAllowStructs(key, "key");
1113 return Add(key, value, KeyCollisionBehavior.ThrowIfValueDifferent, Origin).Finalize(this);
1114 }
1115
1121
1123 {
1124 Requires.NotNullAllowStructs(key, "key");
1125 return Add(key, value, KeyCollisionBehavior.SetValue, Origin).Finalize(this);
1126 }
1127
1129 {
1130 Requires.NotNull(items, "items");
1131 return AddRange(items, Origin, KeyCollisionBehavior.SetValue).Finalize(this);
1132 }
1133
1135 {
1136 Requires.NotNullAllowStructs(key, "key");
1137 return Remove(key, Origin).Finalize(this);
1138 }
1139
1141 {
1142 Requires.NotNull(keys, "keys");
1143 int num = _count;
1145 foreach (TKey key in keys)
1146 {
1147 int hashCode = KeyComparer.GetHashCode(key);
1149 {
1150 OperationResult result;
1153 if (result == OperationResult.SizeChanged)
1154 {
1155 num--;
1156 }
1157 }
1158 }
1159 return Wrap(sortedInt32KeyNode, num);
1160 }
1161
1162 public bool ContainsKey(TKey key)
1163 {
1164 Requires.NotNullAllowStructs(key, "key");
1165 return ContainsKey(key, Origin);
1166 }
1167
1169 {
1170 return Contains(pair, Origin);
1171 }
1172
1173 public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)
1174 {
1175 Requires.NotNullAllowStructs(key, "key");
1176 return TryGetValue(key, Origin, out value);
1177 }
1178
1179 public bool TryGetKey(TKey equalKey, out TKey actualKey)
1180 {
1181 Requires.NotNullAllowStructs(equalKey, "equalKey");
1183 }
1184
1186 {
1187 if (keyComparer == null)
1188 {
1189 keyComparer = EqualityComparer<TKey>.Default;
1190 }
1191 if (valueComparer == null)
1192 {
1194 }
1195 if (KeyComparer == keyComparer)
1196 {
1198 {
1199 return this;
1200 }
1203 }
1206 return immutableDictionary.AddRange(this, avoidToHashMap: true);
1207 }
1208
1213
1214 public bool ContainsValue(TValue value)
1215 {
1217 {
1218 while (enumerator.MoveNext())
1219 {
1220 KeyValuePair<TKey, TValue> current = enumerator.Current;
1221 if (ValueComparer.Equals(value, current.Value))
1222 {
1223 return true;
1224 }
1225 }
1226 }
1227 return false;
1228 }
1229
1231 {
1232 return new Enumerator(_root);
1233 }
1234
1239
1244
1249
1254
1259
1264
1266 {
1267 throw new NotSupportedException();
1268 }
1269
1271 {
1272 throw new NotSupportedException();
1273 }
1274
1279
1284
1289
1291 {
1292 Requires.NotNull(array, "array");
1293 Requires.Range(arrayIndex >= 0, "arrayIndex");
1294 Requires.Range(array.Length >= arrayIndex + Count, "arrayIndex");
1296 while (enumerator.MoveNext())
1297 {
1298 KeyValuePair<TKey, TValue> current = enumerator.Current;
1299 array[arrayIndex++] = current;
1300 }
1301 }
1302
1303 void IDictionary.Add(object key, object value)
1304 {
1305 throw new NotSupportedException();
1306 }
1307
1309 {
1310 return ContainsKey((TKey)key);
1311 }
1312
1317
1319 {
1320 throw new NotSupportedException();
1321 }
1322
1324 {
1325 throw new NotSupportedException();
1326 }
1327
1329 {
1330 Requires.NotNull(array, "array");
1331 Requires.Range(arrayIndex >= 0, "arrayIndex");
1332 Requires.Range(array.Length >= arrayIndex + Count, "arrayIndex");
1334 while (enumerator.MoveNext())
1335 {
1336 KeyValuePair<TKey, TValue> current = enumerator.Current;
1337 array.SetValue(new DictionaryEntry(current.Key, current.Value), arrayIndex++);
1338 }
1339 }
1340
1349
1351 {
1352 return GetEnumerator();
1353 }
1354
1356 {
1357 Requires.NotNull(comparers, "comparers");
1358 if (Empty._comparers != comparers)
1359 {
1361 }
1362 return Empty;
1363 }
1364
1366 {
1368 if (other != null)
1369 {
1370 return true;
1371 }
1373 {
1374 other = builder.ToImmutable();
1375 return true;
1376 }
1377 return false;
1378 }
1379
1380 private static bool ContainsKey(TKey key, MutationInput origin)
1381 {
1382 int hashCode = origin.KeyComparer.GetHashCode(key);
1383 TValue value2;
1384 if (origin.Root.TryGetValue(hashCode, out var value))
1385 {
1386 return value.TryGetValue(key, origin.Comparers, out value2);
1387 }
1388 return false;
1389 }
1390
1392 {
1393 int hashCode = origin.KeyComparer.GetHashCode(keyValuePair.Key);
1394 if (origin.Root.TryGetValue(hashCode, out var value))
1395 {
1396 if (value.TryGetValue(keyValuePair.Key, origin.Comparers, out var value2))
1397 {
1398 return origin.ValueComparer.Equals(value2, keyValuePair.Value);
1399 }
1400 return false;
1401 }
1402 return false;
1403 }
1404
1405 private static bool TryGetValue(TKey key, MutationInput origin, [MaybeNullWhen(false)] out TValue value)
1406 {
1407 int hashCode = origin.KeyComparer.GetHashCode(key);
1408 if (origin.Root.TryGetValue(hashCode, out var value2))
1409 {
1410 return value2.TryGetValue(key, origin.Comparers, out value);
1411 }
1412 value = default(TValue);
1413 return false;
1414 }
1415
1416 private static bool TryGetKey(TKey equalKey, MutationInput origin, out TKey actualKey)
1417 {
1418 int hashCode = origin.KeyComparer.GetHashCode(equalKey);
1419 if (origin.Root.TryGetValue(hashCode, out var value))
1420 {
1421 return value.TryGetKey(equalKey, origin.Comparers, out actualKey);
1422 }
1424 return false;
1425 }
1426
1428 {
1429 Requires.NotNullAllowStructs(key, "key");
1430 int hashCode = origin.KeyComparer.GetHashCode(key);
1431 OperationResult result;
1432 HashBucket newBucket = origin.Root.GetValueOrDefault(hashCode).Add(key, value, origin.KeyOnlyComparer, origin.ValueComparer, behavior, out result);
1433 if (result == OperationResult.NoChangeRequired)
1434 {
1435 return new MutationResult(origin);
1436 }
1438 return new MutationResult(root, (result == OperationResult.SizeChanged) ? 1 : 0);
1439 }
1440
1442 {
1443 Requires.NotNull(items, "items");
1444 int num = 0;
1446 foreach (KeyValuePair<TKey, TValue> item in items)
1447 {
1448 Requires.NotNullAllowStructs(item.Key, "Key");
1449 int hashCode = origin.KeyComparer.GetHashCode(item.Key);
1450 OperationResult result;
1451 HashBucket newBucket = sortedInt32KeyNode.GetValueOrDefault(hashCode).Add(item.Key, item.Value, origin.KeyOnlyComparer, origin.ValueComparer, collisionBehavior, out result);
1453 if (result == OperationResult.SizeChanged)
1454 {
1455 num++;
1456 }
1457 }
1458 return new MutationResult(sortedInt32KeyNode, num);
1459 }
1460
1461 private static MutationResult Remove(TKey key, MutationInput origin)
1462 {
1463 int hashCode = origin.KeyComparer.GetHashCode(key);
1464 if (origin.Root.TryGetValue(hashCode, out var value))
1465 {
1466 OperationResult result;
1467 SortedInt32KeyNode<HashBucket> root = UpdateRoot(origin.Root, hashCode, value.Remove(key, origin.KeyOnlyComparer, out result), origin.HashBucketComparer);
1468 return new MutationResult(root, (result == OperationResult.SizeChanged) ? (-1) : 0);
1469 }
1470 return new MutationResult(origin);
1471 }
1472
1474 {
1475 bool mutated;
1476 if (newBucket.IsEmpty)
1477 {
1478 return root.Remove(hashCode, out mutated);
1479 }
1481 return root.SetItem(hashCode, newBucket, hashBucketComparer, out replacedExistingValue, out mutated);
1482 }
1483
1485 {
1486 Requires.NotNull(root, "root");
1487 Requires.NotNull(comparers, "comparers");
1488 Requires.Range(count >= 0, "count");
1490 }
1491
1493 {
1494 if (root == null)
1495 {
1496 return Clear();
1497 }
1498 if (_root != root)
1499 {
1500 if (!root.IsEmpty)
1501 {
1503 }
1504 return Clear();
1505 }
1506 return this;
1507 }
1508
1510 {
1511 Requires.NotNull(pairs, "pairs");
1513 {
1514 return other.WithComparers(KeyComparer, ValueComparer);
1515 }
1516 return AddRange(pairs, Origin).Finalize(this);
1517 }
1518}
KeyCollisionBehavior
bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)
bool ICollection< KeyValuePair< TKey, TValue > >. Remove(KeyValuePair< TKey, TValue > keyValuePair)
void CopyTo(KeyValuePair< TKey, TValue >[] array, int index)
bool ICollection< KeyValuePair< TKey, TValue > >. Contains(KeyValuePair< TKey, TValue > keyValuePair)
void AddRange(IEnumerable< KeyValuePair< TKey, TValue > > collection)
bool ICollection< KeyValuePair< TKey, TValue > >. IsReadOnly
void Add(TKey key, TValue value)
void AddRange(IEnumerable< KeyValuePair< TKey, TValue > > items)
bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)
Comparers WithValueComparer(IEqualityComparer< TValue > valueComparer)
Comparers(IEqualityComparer< TKey > keyComparer, IEqualityComparer< TValue > valueComparer)
static Comparers Get(IEqualityComparer< TKey > keyComparer, IEqualityComparer< TValue > valueComparer)
IEqualityComparer< KeyValuePair< TKey, TValue > > KeyOnlyComparer
ImmutableDictionary< TKey, TValue > WithComparers(IEqualityComparer< TKey >? keyComparer)
ImmutableDictionary< TKey, TValue > SetItem(TKey key, TValue value)
bool Contains(KeyValuePair< TKey, TValue > pair)
static bool TryGetValue(TKey key, MutationInput origin, [MaybeNullWhen(false)] out TValue value)
readonly SortedInt32KeyNode< HashBucket > _root
static ImmutableDictionary< TKey, TValue > Wrap(SortedInt32KeyNode< HashBucket > root, Comparers comparers, int count)
ImmutableDictionary< TKey, TValue > SetItems(IEnumerable< KeyValuePair< TKey, TValue > > items)
ImmutableDictionary< TKey, TValue > Add(TKey key, TValue value)
bool TryGetKey(TKey equalKey, out TKey actualKey)
ImmutableDictionary< TKey, TValue > WithComparers(IEqualityComparer< TKey >? keyComparer, IEqualityComparer< TValue >? valueComparer)
ImmutableDictionary< TKey, TValue > Remove(TKey key)
static bool Contains(KeyValuePair< TKey, TValue > keyValuePair, MutationInput origin)
static MutationResult Remove(TKey key, MutationInput origin)
static ImmutableDictionary< TKey, TValue > EmptyWithComparers(Comparers comparers)
static readonly Action< KeyValuePair< int, HashBucket > > s_FreezeBucketAction
static ? TValue GetValueOrDefault< TKey, TValue >(this IImmutableDictionary< TKey, TValue > dictionary, TKey key)
static ImmutableDictionary< TKey, TValue > ToImmutableDictionary< TSource, TKey, TValue >(this IEnumerable< TSource > source, Func< TSource, TKey > keySelector, Func< TSource, TValue > elementSelector, IEqualityComparer< TKey >? keyComparer, IEqualityComparer< TValue >? valueComparer)
static SortedInt32KeyNode< HashBucket > UpdateRoot(SortedInt32KeyNode< HashBucket > root, int hashCode, HashBucket newBucket, IEqualityComparer< HashBucket > hashBucketComparer)
ImmutableDictionary< TKey, TValue > RemoveRange(IEnumerable< TKey > keys)
static ImmutableDictionary< TKey, TSource > ToImmutableDictionary< TSource, TKey >(this IEnumerable< TSource > source, Func< TSource, TKey > keySelector)
ImmutableDictionary< TKey, TValue > Clear()
static bool ContainsKey(TKey key, MutationInput origin)
static MutationResult AddRange(IEnumerable< KeyValuePair< TKey, TValue > > items, MutationInput origin, KeyCollisionBehavior collisionBehavior=KeyCollisionBehavior.ThrowIfValueDifferent)
static MutationResult Add(TKey key, TValue value, KeyCollisionBehavior behavior, MutationInput origin)
bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)
static bool Contains< TKey, TValue >(this IImmutableDictionary< TKey, TValue > map, TKey key, TValue value)
static ImmutableDictionary< TKey, TValue > Create< TKey, TValue >()
ImmutableDictionary< TKey, TValue > AddRange(IEnumerable< KeyValuePair< TKey, TValue > > pairs, bool avoidToHashMap)
ImmutableDictionary< TKey, TValue > AddRange(IEnumerable< KeyValuePair< TKey, TValue > > pairs)
static ImmutableDictionary< TKey, TValue > CreateRange< TKey, TValue >(IEnumerable< KeyValuePair< TKey, TValue > > items)
ImmutableDictionary< TKey, TValue > Wrap(SortedInt32KeyNode< HashBucket > root, int adjustedCountIfDifferentRoot)
static ImmutableDictionary< TKey, TValue > ToImmutableDictionary< TKey, TValue >(this ImmutableDictionary< TKey, TValue >.Builder builder)
static bool TryGetKey(TKey equalKey, MutationInput origin, out TKey actualKey)
ImmutableDictionary(SortedInt32KeyNode< HashBucket > root, Comparers comparers, int count)
static readonly ImmutableDictionary< TKey, TValue > Empty
static bool TryCastToImmutableMap(IEnumerable< KeyValuePair< TKey, TValue > > sequence, [NotNullWhen(true)] out ImmutableDictionary< TKey, TValue > other)
static ImmutableDictionary< TKey, TValue >.Builder CreateBuilder< TKey, TValue >()
ImmutableList< T > RemoveAt(int index)
int IndexOf(T item, int index, int count, IEqualityComparer< T >? equalityComparer)
static void Range(bool condition, string? parameterName, string? message=null)
Definition Requires.cs:40
static string Format(string resourceFormat, object p1)
Definition SR.cs:118
static string CollectionModifiedDuringEnumeration
Definition SR.cs:26
static string DuplicateKey
Definition SR.cs:28
static string Arg_KeyNotFoundWithKey
Definition SR.cs:94
Definition SR.cs:7
static int CompareExchange(ref int location1, int value, int comparand)
void CopyTo(Array array, int index)
new IDictionaryEnumerator GetEnumerator()
void Add(object key, object? value)
new bool Equals(object? x, object? y)
Enumerator(SortedInt32KeyNode< HashBucket > root, Builder? builder=null)
SortedInt32KeyNode< HashBucket >.Enumerator _mapEnumerator
ImmutableList< KeyValuePair< TKey, TValue > >.Enumerator _additionalEnumerator
readonly ImmutableList< KeyValuePair< TKey, TValue > >.Node _additionalElements
HashBucket Remove(TKey key, IEqualityComparer< KeyValuePair< TKey, TValue > > keyOnlyComparer, out OperationResult result)
HashBucket(KeyValuePair< TKey, TValue > firstElement, ImmutableList< KeyValuePair< TKey, TValue > >.Node additionalElements=null)
bool TryGetValue(TKey key, Comparers comparers, [MaybeNullWhen(false)] out TValue value)
bool TryGetKey(TKey equalKey, Comparers comparers, out TKey actualKey)
HashBucket Add(TKey key, TValue value, IEqualityComparer< KeyValuePair< TKey, TValue > > keyOnlyComparer, IEqualityComparer< TValue > valueComparer, KeyCollisionBehavior behavior, out OperationResult result)
ImmutableList< KeyValuePair< TKey, TValue > >.Node AdditionalElements
IEqualityComparer< KeyValuePair< TKey, TValue > > KeyOnlyComparer
MutationInput(SortedInt32KeyNode< HashBucket > root, Comparers comparers)
ImmutableDictionary< TKey, TValue > Finalize(ImmutableDictionary< TKey, TValue > priorMap)
MutationResult(SortedInt32KeyNode< HashBucket > root, int countAdjustment)