< Summary

Information
Line coverage
97%
Covered lines: 356
Uncovered lines: 9
Coverable lines: 365
Total lines: 1116
Line coverage: 97.5%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
File 1: GetViewHashCode()0%220100%
File 2: ScriptableDictionary()0%110100%
File 2: get_Item(...)0%330100%
File 2: set_Item(...)0%11088.89%
File 2: get_IsFixedSize()0%110100%
File 2: get_IsSynchronized()0%110100%
File 2: get_SyncRoot()0%110100%
File 2: get_Values()0%110100%
File 2: get_Keys()0%110100%
File 2: System.Collections.Generic.IDictionary<TKey,TValue>.get_Keys()0%2100%
File 2: System.Collections.Generic.IDictionary<TKey,TValue>.get_Values()0%2100%
File 2: System.Collections.Generic.IReadOnlyDictionary<TKey,TValue>.get_Keys()0%110100%
File 2: System.Collections.Generic.IReadOnlyDictionary<TKey,TValue>.get_Values()0%110100%
File 2: IsValid()0%660100%
File 2: IsIndexUnique(...)0%440100%
File 2: Add(...)0%110100%
File 2: Add(...)0%11088.89%
File 2: System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<TKey,TValue>>.Add(...)0%110100%
File 2: AddInternal(...)0%110100%
File 2: Clear()0%220100%
File 2: ContainsKey(...)0%110100%
File 2: ContainsValue(...)0%110100%
File 2: Contains(...)0%220100%
File 2: System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<TKey,TValue>>.Contains(...)0%220100%
File 2: CopyTo(...)0%110100%
File 2: System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<TKey,TValue>>.CopyTo(...)0%110100%
File 2: EnsureCapacity(...)0%330100%
File 2: GetEnumerator()0%110100%
File 2: GetEnumerator()0%110100%
File 2: System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey,TValue>>.GetEnumerator()0%110100%
File 2: GetEnumerator()0%110100%
File 2: Remove(...)0%110100%
File 2: Remove(...)0%2100%
File 2: Remove(...)0%220100%
File 2: System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<TKey,TValue>>.Remove(...)0%330100%
File 2: RemoveInternal(...)0%220100%
File 2: SetValue(...)0%440100%
File 2: TrimExcess()0%110100%
File 2: TrimExcess(...)0%110100%
File 2: TryAdd(...)0%110100%
File 2: TryAddInternal(...)0%220100%
File 2: TryFindKey(...)0%330100%
File 2: TryFindValue(...)0%330100%
File 2: TryGetValue(...)0%110100%
File 2: InvokeCollectionChanged(...)0%330100%
File 2: OnBeforeSerialize()0%110100%
File 2: OnAfterDeserialize()0%330100%
File 2: OnPreStart()0%440100%
File 2: WarnIfLeftOverSubscribers()0%110100%
File 2: WarnIfLeftOverObjects()0%440100%
File 2: ClearSubscribers(...)0%220100%
File 2: OnDisabled()0%110100%

File(s)

./Packages/se.hertzole.scriptable-values/Runtime/Collections/Core/ScriptableDictionary.Bindings.cs

#LineLine coverage
 1#if SCRIPTABLE_VALUES_RUNTIME_BINDING && SCRIPTABLE_VALUES_UITOOLKIT
 2using System.Collections.Generic;
 3
 4namespace Hertzole.ScriptableValues
 5{
 6    partial class ScriptableDictionary<TKey, TValue>
 7    {
 8        /// <inheritdoc />
 9        protected override long GetViewHashCode()
 7210        {
 11            unchecked
 7212            {
 7213                long hash = 17;
 7214                hash = hash * 23 + base.GetViewHashCode();
 7215                hash = hash * 23 + Count.GetHashCode();
 7216                hash = hash * 23 + IsReadOnly.GetHashCode();
 7217                hash = hash * 23 + ClearOnStart.GetHashCode();
 7218                hash = hash * 23 + SetEqualityCheck.GetHashCode();
 19
 7220                EqualityComparer<TKey> keyComparer = EqualityComparer<TKey>.Default;
 7221                EqualityComparer<TValue> valueComparer = EqualityComparer<TValue>.Default;
 22
 28823                for (int i = 0; i < keys.Count; i++)
 7224                {
 7225                    hash = hash * 23 + keyComparer.GetHashCode(keys[i]);
 7226                    hash = hash * 23 + valueComparer.GetHashCode(values[i]);
 7227                }
 28
 7229                return hash;
 30            }
 7231        }
 32    }
 33}
 34#endif

./Packages/se.hertzole.scriptable-values/Runtime/Collections/Core/ScriptableDictionary.cs

#LineLine coverage
 1#nullable enable
 2
 3using System;
 4using System.Collections;
 5using System.Collections.Generic;
 6using System.Collections.Specialized;
 7using System.ComponentModel;
 8using System.Diagnostics;
 9using System.Diagnostics.CodeAnalysis;
 10using System.Runtime.CompilerServices;
 11using Hertzole.ScriptableValues.Helpers;
 12using UnityEngine;
 13using UnityEngine.Assertions;
 14using Debug = UnityEngine.Debug;
 15#if SCRIPTABLE_VALUES_PROPERTIES
 16using Unity.Properties;
 17#endif
 18
 19namespace Hertzole.ScriptableValues
 20{
 21    /// <summary>
 22    ///     Base class for all <see cref="ScriptableDictionary{TKey,TValue}" />.
 23    /// </summary>
 24    /// <remarks>You should probably inherit from <see cref="ScriptableDictionary{TKey,TValue}" /> instead.</remarks>
 25#if UNITY_EDITOR
 26    [HelpURL(Documentation.SCRIPTABLE_DICTIONARY_URL)]
 27#endif
 28    public abstract class ScriptableDictionary : RuntimeScriptableObject, ICanBeReadOnly, INotifyCollectionChanged
 29    {
 30        public static readonly PropertyChangedEventArgs isReadOnlyChangedEventArgs = new PropertyChangedEventArgs(nameof
 31        public static readonly PropertyChangingEventArgs isReadOnlyChangingEventArgs = new PropertyChangingEventArgs(nam
 32
 33        public static readonly PropertyChangedEventArgs setEqualityCheckChangedEventArgs = new PropertyChangedEventArgs(
 34        public static readonly PropertyChangingEventArgs setEqualityCheckChangingEventArgs = new PropertyChangingEventAr
 35
 36        public static readonly PropertyChangedEventArgs clearOnStartChangedEventArgs = new PropertyChangedEventArgs(name
 37        public static readonly PropertyChangingEventArgs clearOnStartChangingEventArgs = new PropertyChangingEventArgs(n
 38
 39        public static readonly PropertyChangedEventArgs countChangedEventArgs = new PropertyChangedEventArgs(nameof(Coun
 40        public static readonly PropertyChangingEventArgs countChangingEventArgs = new PropertyChangingEventArgs(nameof(C
 41
 42        // Internal event for the INotifyCollectionChanged interface as we don't want to expose that event directly.
 43        private event NotifyCollectionChangedEventHandler? OnInternalCollectionChanged;
 44
 45        /// <inheritdoc />
 46        event NotifyCollectionChangedEventHandler INotifyCollectionChanged.CollectionChanged
 47        {
 48            add { OnInternalCollectionChanged += value; }
 49            remove { OnInternalCollectionChanged -= value; }
 50        }
 51
 52        /// <summary>
 53        ///     If <c>true</c>, an equality check will be run before setting an item through the indexer to make sure th
 54        ///     object is not the same as the old one.
 55        /// </summary>
 56#if SCRIPTABLE_VALUES_PROPERTIES
 57        [CreateProperty]
 58#endif
 59        public abstract bool SetEqualityCheck { get; set; }
 60
 61        /// <summary>
 62        ///     If <c>true</c>, the <see cref="ScriptableDictionary{TKey,TValue}" /> will be cleared on play mode start/
 63        /// </summary>
 64#if SCRIPTABLE_VALUES_PROPERTIES
 65        [CreateProperty]
 66#endif
 67        public abstract bool ClearOnStart { get; set; }
 68
 69        /// <summary>
 70        ///     Gets the number of key/value pairs contained in the <see cref="ScriptableDictionary{TKey,TValue}" />.
 71        /// </summary>
 72#if SCRIPTABLE_VALUES_PROPERTIES
 73#if SCRIPTABLE_VALUES_PROPERTIES_SUPPORTS_READONLY
 74        [CreateProperty(ReadOnly = true)]
 75#else
 76        [CreateProperty]
 77#endif // SCRIPTABLE_VALUES_PROPERTIES_SUPPORTS_READONLY
 78#endif // SCRIPTABLE_VALUES_PROPERTIES
 79        public abstract int Count { get; protected set; }
 80
 81        /// <summary>
 82        ///     If read only, the <see cref="ScriptableDictionary{TKey,TValue}" /> cannot be changed at runtime and won'
 83        ///     cleared on start.
 84        /// </summary>
 85#if SCRIPTABLE_VALUES_PROPERTIES
 86        [CreateProperty]
 87#endif
 88        public abstract bool IsReadOnly { get; set; }
 89
 90        internal virtual bool IsValid()
 91        {
 92            return false;
 93        }
 94
 95        internal virtual bool IsIndexUnique(int index)
 96        {
 97            return false;
 98        }
 99
 100        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 101        internal bool IsCollectionChangedNull()
 102        {
 103            return OnInternalCollectionChanged == null;
 104        }
 105
 106        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 107        internal void InvokeCollectionChangedBase(NotifyCollectionChangedEventArgs args)
 108        {
 109            Assert.IsNotNull(OnInternalCollectionChanged, "Need to check for null before invoking the event using " + na
 110
 111            // The event should already be checked for null here.
 112            OnInternalCollectionChanged!.Invoke(this, args);
 113        }
 114
 115        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 116        internal void ClearBaseSubscribers()
 117        {
 118            OnInternalCollectionChanged = null;
 119        }
 120
 121        /// <inheritdoc />
 122        protected override void WarnIfLeftOverSubscribers()
 123        {
 124            base.WarnIfLeftOverSubscribers();
 125            EventHelper.WarnIfLeftOverSubscribers(OnInternalCollectionChanged, "INotifyCollectionChanged.CollectionChang
 126        }
 127
 128        /// <summary>
 129        ///     Removes all keys and values from the <see cref="ScriptableDictionary{TKey,TValue}" />.
 130        /// </summary>
 131        /// <exception cref="System.Data.ReadOnlyException">If the object is read-only and the application is playing.</
 132        public abstract void Clear();
 133
 134        /// <summary>
 135        ///     Ensures that the dictionary can hold up to a specified number of entries without any further expansion o
 136        ///     backing storage.
 137        /// </summary>
 138        /// <param name="capacity">The number of entries.</param>
 139        /// <returns>The current capacity of the <see cref="ScriptableDictionary{TKey,TValue}" />.</returns>
 140        /// <exception cref="ArgumentOutOfRangeException"><paramref name="capacity" /> is less than 0.</exception>
 141        public abstract int EnsureCapacity(int capacity);
 142
 143        /// <summary>
 144        ///     Sets the capacity of this <see cref="ScriptableDictionary{TKey,TValue}" /> to what it would be if it had
 145        ///     originally initialized with all its entries.
 146        /// </summary>
 147        public abstract void TrimExcess();
 148
 149        /// <summary>
 150        ///     Sets the capacity of this <see cref="ScriptableDictionary{TKey,TValue}" /> to hold up a specified number
 151        ///     without any further expansion of its
 152        ///     backing storage.
 153        /// </summary>
 154        /// <param name="capacity">The new capacity.</param>
 155        /// <exception cref="ArgumentOutOfRangeException">
 156        ///     <paramref name="capacity" /> is less than the number of items in the
 157        ///     <see cref="ScriptableDictionary{TKey,TValue}" />.
 158        /// </exception>
 159        public abstract void TrimExcess(int capacity);
 160    }
 161
 162    /// <summary>
 163    ///     A <see cref="ScriptableObject" /> that holds a <see cref="System.Collections.Generic.Dictionary{TKey, TValue
 164    /// </summary>
 165    /// <typeparam name="TKey">The key of the dictionary.</typeparam>
 166    /// <typeparam name="TValue">The value of the dictionary.</typeparam>
 167    public abstract partial class ScriptableDictionary<TKey, TValue> : ScriptableDictionary,
 168        ISerializationCallbackReceiver,
 169        IDictionary<TKey, TValue>,
 170        IReadOnlyDictionary<TKey, TValue>,
 171        INotifyScriptableCollectionChanged<KeyValuePair<TKey, TValue>>,
 172        IDictionary where TKey : notnull
 173    {
 174        [SerializeField]
 175        [EditorTooltip("If read only, the dictionary cannot be changed at runtime and won't be cleared on start.")]
 176#if SCRIPTABLE_VALUES_PROPERTIES
 177        [DontCreateProperty]
 178#endif
 1288179        internal bool isReadOnly = false;
 180        [SerializeField]
 181        [EditorTooltip(
 182            "If true, an equality check will be run before setting an item through the indexer to make sure the new obje
 183#if SCRIPTABLE_VALUES_PROPERTIES
 184        [DontCreateProperty]
 185#endif
 1288186        internal bool setEqualityCheck = true;
 187        [SerializeField]
 188        [EditorTooltip("If true, the dictionary will be cleared on play mode start/game boot.")]
 189#if SCRIPTABLE_VALUES_PROPERTIES
 190        [DontCreateProperty]
 191#endif
 1288192        internal bool clearOnStart = true;
 193
 194        [SerializeField]
 195#if SCRIPTABLE_VALUES_PROPERTIES
 196        [DontCreateProperty]
 197#endif
 1288198        internal List<TKey> keys = new List<TKey>();
 199        [SerializeField]
 200#if SCRIPTABLE_VALUES_PROPERTIES
 201        [DontCreateProperty]
 202#endif
 1288203        internal List<TValue> values = new List<TValue>();
 204
 1288205        private int count = 0;
 206
 1288207        internal Dictionary<TKey, TValue> dictionary = new Dictionary<TKey, TValue>();
 208
 209        object? IDictionary.this[object key]
 210        {
 36211            get { return EqualityHelper.IsSameType(key, out TKey? newKey) ? dictionary[newKey] : null; }
 212            set
 114213            {
 114214                Guard.IsNotNull(key, nameof(key));
 108215                Guard.ThrowIfNullAndNullsAreIllegal<TValue>(value, nameof(value));
 216
 217                try
 108218                {
 108219                    TKey tempKey = (TKey) key;
 220                    try
 102221                    {
 102222                        SetValue(tempKey, (TValue) value!);
 72223                    }
 6224                    catch (InvalidCastException)
 6225                    {
 6226                        ThrowHelper.ThrowWrongExpectedValueType<TValue>(value);
 0227                    }
 72228                }
 6229                catch (InvalidCastException)
 6230                {
 6231                    ThrowHelper.ThrowWrongExpectedValueType<TKey>(key);
 0232                }
 72233            }
 234        }
 235
 236        public TValue this[TKey key]
 237        {
 396238            get { return dictionary[key]; }
 600239            set { SetValue(key, value); }
 240        }
 241
 242        /// <summary>
 243        ///     Gets or sets the <see cref="IEqualityComparer{T}" /> that is used to determine equality of keys for the
 244        ///     <see cref="ScriptableDictionary{TKey,TValue}" />.
 245        /// </summary>
 246        public IEqualityComparer<TKey> Comparer
 247        {
 522248            get { return dictionary.Comparer; }
 249            set
 12250            {
 251                // If you update the comparer, we need to re-create the whole dictionary.
 252                // Make sure it's a new comparer than the old one.
 12253                if (!EqualityComparer<IEqualityComparer<TKey>>.Default.Equals(dictionary.Comparer, value))
 12254                {
 12255                    Dictionary<TKey, TValue> newDictionary = new Dictionary<TKey, TValue>(dictionary, value);
 256
 12257                    dictionary = newDictionary;
 12258                }
 12259            }
 260        }
 261
 262        /// <inheritdoc cref="ScriptableDictionary.Count" />
 263        public sealed override int Count
 264        {
 265            get
 1552266            {
 1552267                Assert.AreEqual(dictionary.Count, count, "Dictionary count is not the same as the internal count.");
 1552268                return count;
 1552269            }
 270            protected set
 3212271            {
 3212272                SetField(ref count, value, countChangingEventArgs, countChangedEventArgs);
 3212273                Assert.AreEqual(dictionary.Count, count);
 3212274            }
 275        }
 276
 277        /// <inheritdoc cref="ScriptableDictionary.IsReadOnly" />
 278        public override bool IsReadOnly
 279        {
 9120280            get { return isReadOnly; }
 4764281            set { SetField(ref isReadOnly, value, isReadOnlyChangingEventArgs, isReadOnlyChangedEventArgs); }
 282        }
 283
 284        /// <inheritdoc />
 285        public override bool SetEqualityCheck
 286        {
 384287            get { return setEqualityCheck; }
 294288            set { SetField(ref setEqualityCheck, value, setEqualityCheckChangingEventArgs, setEqualityCheckChangedEventA
 289        }
 290
 291        /// <inheritdoc />
 292        public override bool ClearOnStart
 293        {
 384294            get { return clearOnStart; }
 258295            set { SetField(ref clearOnStart, value, clearOnStartChangingEventArgs, clearOnStartChangedEventArgs); }
 296        }
 297
 298        /// <summary>
 299        ///     Gets a collection containing the keys in the dictionary.
 300        /// </summary>
 301        public Dictionary<TKey, TValue>.KeyCollection Keys
 302        {
 54303            get { return dictionary.Keys; }
 304        }
 305
 306        /// <summary>
 307        ///     Gets a collection containing the values in the <see cref="ScriptableDictionary{TKey,TValue}" />.
 308        /// </summary>
 309        public Dictionary<TKey, TValue>.ValueCollection Values
 310        {
 54311            get { return dictionary.Values; }
 312        }
 313
 314        bool IDictionary.IsFixedSize
 315        {
 36316            get { return isReadOnly; }
 317        }
 318        bool ICollection.IsSynchronized
 319        {
 18320            get { return false; }
 321        }
 322        object ICollection.SyncRoot
 323        {
 18324            get { return this; }
 325        }
 326        ICollection IDictionary.Values
 327        {
 18328            get { return dictionary.Values; }
 329        }
 330        ICollection IDictionary.Keys
 331        {
 18332            get { return dictionary.Keys; }
 333        }
 334        ICollection<TKey> IDictionary<TKey, TValue>.Keys
 335        {
 0336            get { return dictionary.Keys; }
 337        }
 338
 339        ICollection<TValue> IDictionary<TKey, TValue>.Values
 340        {
 0341            get { return dictionary.Values; }
 342        }
 343
 344        IEnumerable<TKey> IReadOnlyDictionary<TKey, TValue>.Keys
 345        {
 18346            get { return dictionary.Keys; }
 347        }
 348        IEnumerable<TValue> IReadOnlyDictionary<TKey, TValue>.Values
 349        {
 18350            get { return dictionary.Values; }
 351        }
 352
 353        /// <summary>
 354        ///     Occurs when an item is added, removed, replaced, or the entire <see cref="ScriptableDictionary{TKey, TVa
 355        ///     refreshed.
 356        /// </summary>
 357        public event CollectionChangedEventHandler<KeyValuePair<TKey, TValue>>? OnCollectionChanged;
 358
 359        /// <summary>
 360        ///     Checks if the dictionary is a valid dictionary by checking the keys and values.
 361        /// </summary>
 362        /// <returns><c>true</c> if the dictionary is valid; otherwise, <c>false</c>.</returns>
 363        internal override bool IsValid()
 48364        {
 365            // If the keys and values are not the same length, the dictionary is invalid.
 48366            if (keys.Count != values.Count)
 24367            {
 24368                return false;
 369            }
 370
 371            // Check for duplicate keys.
 168372            for (int i = 0; i < keys.Count; i++)
 72373            {
 480374                for (int j = i; j < keys.Count; j++)
 180375                {
 376                    // Ignore the same index.
 180377                    if (i == j)
 72378                    {
 72379                        continue;
 380                    }
 381
 382                    // There's a duplicate key, the dictionary is invalid.
 108383                    if (Comparer.Equals(keys[i], keys[j]))
 12384                    {
 12385                        return false;
 386                    }
 96387                }
 60388            }
 389
 390            // The dictionary was valid.
 12391            return true;
 48392        }
 393
 394        /// <summary>
 395        ///     Checks if a key at a specific index is unique.
 396        /// </summary>
 397        /// <param name="index">The index to check.</param>
 398        /// <returns><c>true</c> if the index is unique; otherwise, <c>false</c>.</returns>
 399        internal override bool IsIndexUnique(int index)
 24400        {
 401            // Check for duplicate keys with the key at index.
 192402            for (int i = 0; i < keys.Count; i++)
 78403            {
 404                // Ignore the same index.
 78405                if (i == index)
 24406                {
 24407                    continue;
 408                }
 409
 410                // A duplicate key was found, the index is invalid.
 54411                if (Comparer.Equals(keys[i], keys[index]))
 6412                {
 6413                    return false;
 414                }
 48415            }
 416
 417            // The index was valid.
 18418            return true;
 24419        }
 420
 421        /// <summary>
 422        ///     Adds the specified key and value to the <see cref="ScriptableDictionary{TKey, TValue}" />.
 423        /// </summary>
 424        /// <param name="key">The key of the element to add.</param>
 425        /// <param name="value">The value of the element to add. The value can be <c>null</c> for reference types.</para
 426        /// <exception cref="ArgumentNullException"><paramref name="key" /> is <c>null</c>.</exception>
 427        /// <exception cref="ArgumentException">
 428        ///     An element with the same key already exists in the
 429        ///     <see cref="ScriptableDictionary{TKey,TValue}" />
 430        /// </exception>
 431        /// <exception cref="System.Data.ReadOnlyException">If the object is read-only and the application is playing.</
 432        public void Add(TKey key, TValue value)
 912433        {
 912434            AddInternal(key, value);
 888435        }
 436
 437        /// <summary>
 438        ///     Adds the specified key and value to the <see cref="ScriptableDictionary{TKey, TValue}" />.
 439        /// </summary>
 440        /// <param name="key">The key of the element to add.</param>
 441        /// <param name="value">The value of the element to add.</param>
 442        /// <exception cref="ArgumentNullException"><paramref name="key" /> is <c>null</c>.</exception>
 443        /// <exception cref="ArgumentException">
 444        ///     An element with the same key already exists in the
 445        ///     <see cref="ScriptableDictionary{TKey,TValue}" />
 446        /// </exception>
 447        /// <exception cref="ArgumentException">
 448        ///     <paramref name="key" /> does not match <typeparamref name="TKey" /> or
 449        ///     <paramref name="value" /> does not match <typeparamref name="TValue" />
 450        /// </exception>
 451        /// <exception cref="System.Data.ReadOnlyException">If the object is read-only and the application is playing.</
 452        void IDictionary.Add(object key, object? value)
 78453        {
 78454            Guard.ThrowIfNullAndNullsAreIllegal<TKey>(key, nameof(key));
 72455            Guard.ThrowIfNullAndNullsAreIllegal<TValue>(value, nameof(value));
 456
 457            try
 66458            {
 66459                TKey tempKey = (TKey) key;
 460
 461                try
 60462                {
 60463                    AddInternal(tempKey, (TValue) value!);
 30464                }
 6465                catch (InvalidCastException)
 6466                {
 6467                    ThrowHelper.ThrowWrongExpectedValueType<TValue>(value);
 0468                }
 30469            }
 6470            catch (InvalidCastException)
 6471            {
 6472                ThrowHelper.ThrowWrongExpectedValueType<TKey>(key);
 0473            }
 30474        }
 475
 476        /// <summary>
 477        ///     Adds a key/value pair to the <see cref="ScriptableDictionary{TKey, TValue}" />.
 478        /// </summary>
 479        /// <param name="keyValuePair">The key/value pair to add.</param>
 480        /// <exception cref="ArgumentNullException">The key of <paramref name="keyValuePair" /> is <c>null</c>.</excepti
 481        /// <exception cref="ArgumentException">
 482        ///     An element with the same key already exists in the
 483        ///     <see cref="ScriptableDictionary{TKey,TValue}" />
 484        /// </exception>
 485        /// <exception cref="System.Data.ReadOnlyException">If the object is read-only and the application is playing.</
 486        void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> keyValuePair)
 48487        {
 48488            AddInternal(keyValuePair.Key, keyValuePair.Value);
 24489        }
 490
 491        /// <exception cref="ArgumentNullException"><paramref name="key" /> is <c>null</c>.</exception>
 492        /// <exception cref="System.Data.ReadOnlyException">If the object is read-only and the application is playing.</
 493        /// <exception cref="ArgumentException">
 494        ///     An element with the same key already exists in the
 495        ///     <see cref="ScriptableDictionary{TKey,TValue}" />
 496        /// </exception>
 497        private void AddInternal(TKey key, TValue value)
 1014498        {
 1014499            Guard.IsNotReadOnly(this, name);
 500
 942501            dictionary.Add(key, value);
 502
 942503            keys.Add(key);
 942504            values.Add(value);
 505
 942506            Count = dictionary.Count;
 507
 942508            Assert.AreEqual(dictionary.Keys.Count, keys.Count);
 942509            Assert.AreEqual(dictionary.Values.Count, values.Count);
 510
 942511            InvokeCollectionChanged(CollectionChangedArgs<KeyValuePair<TKey, TValue>>.Add(new KeyValuePair<TKey, TValue>
 512
 942513            AddStackTrace(1);
 942514        }
 515
 516        /// <inheritdoc cref="ScriptableDictionary.Clear" />
 517        public sealed override void Clear()
 1262518        {
 1262519            Guard.IsNotReadOnly(this, name);
 520
 1238521            if (Count == 0)
 530522            {
 530523                return;
 524            }
 525
 708526            using (CollectionScope<KeyValuePair<TKey, TValue>> scope = new CollectionScope<KeyValuePair<TKey, TValue>>(d
 708527            {
 708528                dictionary.Clear();
 529
 708530                keys.Clear();
 708531                values.Clear();
 532
 708533                Count = 0;
 534
 708535                InvokeCollectionChanged(CollectionChangedArgs<KeyValuePair<TKey, TValue>>.Clear(scope.Span, -1, -1));
 536
 708537                AddStackTrace();
 708538            }
 1238539        }
 540
 541        /// <summary>
 542        ///     Determines whether the <see cref="ScriptableDictionary{TKey,TValue}" /> contains the specified key.
 543        /// </summary>
 544        /// <param name="key">The key to locate in the <see cref="ScriptableDictionary{TKey,TValue}" />.</param>
 545        /// <returns>
 546        ///     <c>true</c> if the <see cref="ScriptableDictionary{TKey,TValue}" /> contains an element with the specifi
 547        ///     key; otherwise, <c>false</c>.
 548        /// </returns>
 549        /// <exception cref="ArgumentNullException"><paramref name="key" /> is <c>null</c>.</exception>
 550        public bool ContainsKey(TKey key)
 24551        {
 24552            return dictionary.ContainsKey(key);
 24553        }
 554
 555        /// <summary>
 556        ///     Determines whether the <see cref="ScriptableDictionary{TKey,TValue}" /> contains a specific value.
 557        /// </summary>
 558        /// <param name="value">
 559        ///     The value to locate in the <see cref="ScriptableDictionary{TKey,TValue}" />. The value can be
 560        ///     <c>null</c> for reference types.
 561        /// </param>
 562        /// <returns>
 563        ///     <c>true</c> if the <see cref="ScriptableDictionary{TKey,TValue}" /> contains the value; otherwise,
 564        ///     <c>false</c>.
 565        /// </returns>
 566        public bool ContainsValue(TValue value)
 12567        {
 12568            return dictionary.ContainsValue(value);
 12569        }
 570
 571        /// <summary>
 572        ///     Determines whether the <see cref="ScriptableDictionary{TKey,TValue}" /> contains an element with the spe
 573        /// </summary>
 574        /// <param name="key">The key to locate in the <see cref="ScriptableDictionary{TKey,TValue}" />.</param>
 575        /// <returns>
 576        ///     <c>true</c> if the key type is the same as <typeparamref name="TKey" /> and the
 577        ///     <see cref="ScriptableDictionary{TKey,TValue}" /> contains the key; otherwise, <c>false</c>.
 578        /// </returns>
 579        /// <exception cref="ArgumentNullException"><paramref name="key" /> is <c>null</c>.</exception>
 580        bool IDictionary.Contains(object key)
 12581        {
 12582            return EqualityHelper.IsSameType(key, out TKey? newKey) && ContainsKey(newKey);
 12583        }
 584
 585        /// <summary>
 586        ///     Determines whether the <see cref="ScriptableDictionary{TKey,TValue}" /> contains a specific key and valu
 587        /// </summary>
 588        /// <param name="item">
 589        ///     The <see cref="KeyValuePair{TKey,TValue}" /> structure to locate in the
 590        ///     <see cref="ScriptableDictionary{TKey,TValue}" />
 591        /// </param>
 592        /// <returns><c>true</c> if the key and value both exist in the dictionary; otherwise, <c>false</c>.</returns>
 593        bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
 18594        {
 18595            return dictionary.ContainsKey(item.Key) && dictionary.ContainsValue(item.Value);
 18596        }
 597
 598        /// <summary>
 599        ///     Copies the elements of the <see cref="ScriptableDictionary{TKey,TValue}" /> to an <see cref="Array" />, 
 600        ///     the specified array index.
 601        /// </summary>
 602        /// <param name="array">The destination array.</param>
 603        /// <param name="index">The index at which copying beings.</param>
 604        void ICollection.CopyTo(Array array, int index)
 6605        {
 6606            Guard.IsNotNull(array, nameof(array));
 607
 6608            ((ICollection) dictionary).CopyTo(array, index);
 6609        }
 610
 611        /// <summary>
 612        ///     Copies the elements of the dictionary to an <see cref="Array" />, starting at a particular array index.
 613        /// </summary>
 614        /// <param name="array">The destination array.</param>
 615        /// <param name="arrayIndex">The index at which copying beings.</param>
 616        void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
 6617        {
 6618            Guard.IsNotNull(array, nameof(array));
 619
 6620            ((ICollection<KeyValuePair<TKey, TValue>>) dictionary).CopyTo(array, arrayIndex);
 6621        }
 622
 623        /// <inheritdoc />
 624        public sealed override int EnsureCapacity(int capacity)
 84625        {
 84626            int result = dictionary.EnsureCapacity(capacity);
 84627            if (keys.Capacity < capacity)
 78628            {
 78629                keys.Capacity = capacity;
 78630            }
 631
 84632            if (values.Capacity < capacity)
 78633            {
 78634                values.Capacity = capacity;
 78635            }
 636
 84637            return result;
 84638        }
 639
 640        /// <summary>
 641        ///     Returns an enumerator that iterates through the <see cref="ScriptableDictionary{TKey,TValue}" />.
 642        /// </summary>
 643        /// <returns>
 644        ///     A <see cref="Dictionary{TKey, TValue}.Enumerator" /> structure for the
 645        ///     <see cref="ScriptableDictionary{TKey,TValue}" />.
 646        /// </returns>
 647        public Dictionary<TKey, TValue>.Enumerator GetEnumerator()
 18648        {
 18649            return dictionary.GetEnumerator();
 18650        }
 651
 652        /// <summary>
 653        ///     Returns an enumerator that iterates through the dictionary.
 654        /// </summary>
 655        /// <returns>A <see cref="Dictionary{TKey, TValue}.Enumerator" /> for the dictionary.</returns>
 656        IDictionaryEnumerator IDictionary.GetEnumerator()
 12657        {
 12658            return ((IDictionary) dictionary).GetEnumerator();
 12659        }
 660
 661        /// <summary>
 662        ///     Returns an enumerator that iterates through the dictionary.
 663        /// </summary>
 664        /// <returns>A <see cref="Dictionary{TKey, TValue}.Enumerator" /> for the dictionary.</returns>
 665        IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()
 6666        {
 6667            return ((IEnumerable<KeyValuePair<TKey, TValue>>) dictionary).GetEnumerator();
 6668        }
 669
 670        /// <summary>
 671        ///     Returns an enumerator that iterates through the dictionary.
 672        /// </summary>
 673        /// <returns>A <see cref="Dictionary{TKey, TValue}.Enumerator" /> for the dictionary.</returns>
 674        IEnumerator IEnumerable.GetEnumerator()
 18675        {
 18676            return ((IEnumerable) dictionary).GetEnumerator();
 18677        }
 678
 679        /// <summary>
 680        ///     Removes the value with the specified key from the <see cref="ScriptableDictionary{TKey,TValue}" />.
 681        /// </summary>
 682        /// <param name="key">The key of the element to remove.</param>
 683        /// <returns>
 684        ///     <c>true</c> if the element is successfully found and removed; otherwise, <c>false</c>.
 685        ///     This method returns <c>false</c> if the key is not found in the <see cref="ScriptableDictionary{TKey,TVa
 686        /// </returns>
 687        /// <exception cref="ArgumentNullException"><paramref name="key" /> is <c>null</c>.</exception>
 688        /// <exception cref="System.Data.ReadOnlyException">If the object is read-only and the application is playing.</
 689        public bool Remove(TKey key)
 90690        {
 90691            return RemoveInternal(key, out _);
 66692        }
 693
 694        /// <summary>
 695        ///     Removes the value with the specified key from the <see cref="ScriptableDictionary{TKey,TValue}" />, and 
 696        ///     element to the <paramref name="value" /> parameter.
 697        /// </summary>
 698        /// <param name="key">The key of the element to remove.</param>
 699        /// <param name="value">
 700        ///     When this method returns, contains the value associated with the specified key, if the key is found;
 701        ///     otherwise, the default value for the type of the <paramref name="value" /> parameter. This parameter is 
 702        ///     uninitialized.
 703        /// </param>
 704        /// <returns><c>true</c> if the element is successfully found and removed; otherwise, <c>false</c>.</returns>
 705        /// <exception cref="ArgumentNullException"><paramref name="key" /> is <c>null</c>.</exception>
 706        /// <exception cref="System.Data.ReadOnlyException">If the object is read-only and the application is playing.</
 707        public bool Remove(TKey key, out TValue value)
 0708        {
 0709            return RemoveInternal(key, out value);
 0710        }
 711
 712        /// <summary>
 713        ///     Removes the value with the specified key from the dictionary.
 714        /// </summary>
 715        /// <param name="key">The key of the element to remove.</param>
 716        /// <exception cref="System.Data.ReadOnlyException">If the object is read-only and the application is playing.</
 717        void IDictionary.Remove(object key)
 102718        {
 102719            if (EqualityHelper.IsSameType(key, out TKey? newKey))
 102720            {
 102721                RemoveInternal(newKey, out _);
 78722            }
 78723        }
 724
 725        /// <summary>
 726        ///     Removes a key/value pair from the dictionary.
 727        /// </summary>
 728        /// <param name="item">The key/value pair to remove.</param>
 729        /// <returns><c>true</c> if the key/value pair was found and removed; otherwise, <c>false</c>.</returns>
 730        /// <exception cref="System.Data.ReadOnlyException">If the object is read-only and the application is playing.</
 731        bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
 96732        {
 96733            if (dictionary.TryGetValue(item.Key, out TValue value) && EqualityHelper.Equals(item.Value, value))
 48734            {
 48735                return RemoveInternal(item.Key, out _);
 736            }
 737
 48738            return false;
 72739        }
 740
 741        /// <exception cref="ArgumentNullException"><c>key</c> is <c>null</c>.</exception>
 742        /// <exception cref="System.Data.ReadOnlyException">If the object is read-only and the application is playing.</
 743        private bool RemoveInternal(TKey key, out TValue value)
 240744        {
 240745            Guard.IsNotReadOnly(this, name);
 746
 168747            bool removed = dictionary.Remove(key, out value);
 168748            if (removed)
 96749            {
 96750                keys.Remove(key);
 96751                values.Remove(value);
 752
 96753                Count = dictionary.Count;
 754
 96755                Assert.AreEqual(dictionary.Keys.Count, keys.Count);
 96756                Assert.AreEqual(dictionary.Values.Count, values.Count);
 757
 96758                InvokeCollectionChanged(CollectionChangedArgs<KeyValuePair<TKey, TValue>>.Remove(new KeyValuePair<TKey, 
 759
 96760                AddStackTrace(1);
 96761            }
 762
 168763            return removed;
 168764        }
 765
 766        /// <summary>
 767        ///     Sets or adds a value to the dictionary.
 768        /// </summary>
 769        /// <param name="key">The key of the element to set.</param>
 770        /// <param name="value">The new value to set.</param>
 771        /// <exception cref="System.Data.ReadOnlyException">If the object is read-only and the application is playing.</
 772        private void SetValue(TKey key, TValue value)
 306773        {
 306774            Guard.IsNotReadOnly(this, name);
 775
 776            // Try to add it first. If it fails, we update the value.
 252777            if (!TryAddInternal(key, value))
 84778            {
 779                // Get the old value from the dictionary.
 84780                TValue? oldValue = dictionary[key];
 781
 782                // If the equality check is enabled, we don't want to set the value if it's the same as the current valu
 84783                if (setEqualityCheck && EqualityHelper.Equals(oldValue, value))
 18784                {
 18785                    return;
 786                }
 787
 788                // Get the index of the value.
 66789                int valueIndex = values.IndexOf(oldValue);
 66790                Assert.AreNotEqual(-1, valueIndex, "The value was not found in the values list.");
 791
 792                // Update the value in the values list.
 66793                values[valueIndex] = value;
 794
 795                // Update the value in the dictionary.
 66796                dictionary[key] = value;
 797
 66798                KeyValuePair<TKey, TValue> oldItem = new KeyValuePair<TKey, TValue>(key, oldValue);
 66799                KeyValuePair<TKey, TValue> newItem = new KeyValuePair<TKey, TValue>(key, value);
 800
 66801                InvokeCollectionChanged(CollectionChangedArgs<KeyValuePair<TKey, TValue>>.Replace(oldItem, newItem, -1))
 802
 66803                AddStackTrace();
 66804            }
 252805        }
 806
 807        /// <inheritdoc />
 808        public sealed override void TrimExcess()
 6809        {
 6810            dictionary.TrimExcess();
 811
 6812            keys.TrimExcess();
 6813            values.TrimExcess();
 814
 6815            AddStackTrace();
 6816        }
 817
 818        /// <inheritdoc />
 819        public sealed override void TrimExcess(int capacity)
 6820        {
 6821            dictionary.TrimExcess(capacity);
 822
 6823            keys.TrimExcess();
 6824            values.TrimExcess();
 825
 6826            AddStackTrace();
 6827        }
 828
 829        /// <summary>
 830        ///     Attempts to add the specified key and value to the <see cref="ScriptableDictionary{TKey,TValue}" />.
 831        /// </summary>
 832        /// <param name="key">The key of the element to add.</param>
 833        /// <param name="value">The value of the element to add. The value can be <c>null</c> for reference types.</para
 834        /// <returns>
 835        ///     <c>true</c> if the key/value pair was added to the <see cref="ScriptableDictionary{TKey,TValue}" />
 836        ///     successfully; <c>false</c> if the key already exists.
 837        /// </returns>
 838        /// <exception cref="ArgumentNullException"><paramref name="key" /> is <c>null</c>.</exception>
 839        /// <exception cref="System.Data.ReadOnlyException">If the object is read-only and the application is playing.</
 840        public bool TryAdd(TKey key, TValue value)
 78841        {
 78842            Guard.IsNotReadOnly(this, name);
 843
 54844            return TryAddInternal(key, value);
 54845        }
 846
 847        private bool TryAddInternal(TKey key, TValue value)
 306848        {
 306849            Assert.IsFalse(isReadOnly, "Trying to add to a read-only dictionary.");
 850
 306851            bool result = dictionary.TryAdd(key, value);
 852
 306853            if (result)
 198854            {
 855                // We must update the lists too so they are in sync with the dictionary.
 198856                keys.Add(key);
 198857                values.Add(value);
 858
 198859                Count = dictionary.Count;
 860
 198861                Assert.AreEqual(dictionary.Keys.Count, keys.Count);
 198862                Assert.AreEqual(dictionary.Values.Count, values.Count);
 863
 198864                InvokeCollectionChanged(CollectionChangedArgs<KeyValuePair<TKey, TValue>>.Add(new KeyValuePair<TKey, TVa
 865
 198866                AddStackTrace(1);
 198867            }
 868
 306869            return result;
 306870        }
 871
 872        /// <summary>
 873        ///     Tries to find a key in the <see cref="ScriptableDictionary{TKey,TValue}" /> that matches the specified p
 874        /// </summary>
 875        /// <param name="predicate">The <see cref="Predicate{T}" /> to check against.</param>
 876        /// <param name="key">
 877        ///     When this method returns, contains the key if it was found. Will be the default value if it wasn't
 878        ///     found.
 879        /// </param>
 880        /// <returns><c>true</c> if a key matching the predicate was found; otherwise, <c>false</c>.</returns>
 881        /// <exception cref="ArgumentNullException"><paramref name="predicate" /> is <c>null</c>.</exception>
 882        public bool TryFindKey(Predicate<TKey> predicate, [NotNullWhen(true)] out TKey? key)
 12883        {
 12884            Guard.IsNotNull(predicate, nameof(predicate));
 885
 54886            foreach (TKey dictionaryKey in dictionary.Keys)
 12887            {
 12888                if (predicate(dictionaryKey))
 6889                {
 6890                    key = dictionaryKey;
 6891                    return true;
 892                }
 6893            }
 894
 6895            key = default;
 6896            return false;
 12897        }
 898
 899        /// <summary>
 900        ///     Tries to find a value in the <see cref="ScriptableDictionary{TKey,TValue}" /> that matches the specified
 901        /// </summary>
 902        /// <param name="predicate">The <see cref="Predicate{T}" /> to check against.</param>
 903        /// <param name="value">
 904        ///     When this method returns, contains the value if it was found. Will be the default value if it
 905        ///     wasn't found.
 906        /// </param>
 907        /// <returns><c>true</c> if a value matching the predicate was found; otherwise, <c>false</c>.</returns>
 908        /// <exception cref="ArgumentNullException"><paramref name="predicate" /> is <c>null</c>.</exception>
 909        public bool TryFindValue(Predicate<TValue> predicate, out TValue? value)
 12910        {
 12911            Guard.IsNotNull(predicate, nameof(predicate));
 912
 54913            foreach (TValue dictionaryValue in dictionary.Values)
 12914            {
 12915                if (predicate(dictionaryValue))
 6916                {
 6917                    value = dictionaryValue;
 6918                    return true;
 919                }
 6920            }
 921
 6922            value = default;
 6923            return false;
 12924        }
 925
 926        /// <summary>
 927        ///     Gets the value associated with the specified key.
 928        /// </summary>
 929        /// <param name="key">The key of the value to get.</param>
 930        /// <param name="value">
 931        ///     When this method returns, contains the value associated with the specified key, if the key is
 932        ///     found; otherwise, the default value for the type of the <paramref name="value" /> parameter. This parame
 933        ///     passed uninitialized.
 934        /// </param>
 935        /// <returns>
 936        ///     <c>true</c> if the <see cref="ScriptableDictionary{TKey,TValue}" /> contains an element with the specifi
 937        ///     key; otherwise, <c>false</c>.
 938        /// </returns>
 939        /// <exception cref="ArgumentNullException"><paramref name="key" /> is <c>null</c>.</exception>
 940        public bool TryGetValue(TKey key, out TValue value)
 12941        {
 12942            return dictionary.TryGetValue(key, out value);
 12943        }
 944
 945        private void InvokeCollectionChanged(CollectionChangedArgs<KeyValuePair<TKey, TValue>> args)
 2010946        {
 2010947            OnCollectionChanged?.Invoke(args);
 2010948            if (!IsCollectionChangedNull())
 84949            {
 84950                InvokeCollectionChangedBase(args.ToNotifyCollectionChangedEventArgs());
 84951            }
 2010952        }
 953
 954        void ISerializationCallbackReceiver.OnBeforeSerialize()
 24955        {
 956            // Does nothing.
 24957        }
 958
 959        /// <summary>
 960        ///     Called after Unity has deserialized this type.
 961        /// </summary>
 962        void ISerializationCallbackReceiver.OnAfterDeserialize()
 24963        {
 964#if DEBUG
 965            // If the dictionary is invalid, stop here.
 24966            if (!IsValid())
 18967            {
 18968                return;
 969            }
 970#endif
 971
 972            // Update the dictionary with the serialized keys and values.
 6973            dictionary.Clear();
 6974            dictionary.EnsureCapacity(keys.Count);
 975
 48976            for (int i = 0; i < keys.Count; i++)
 18977            {
 18978                dictionary.Add(keys[i], values[i]);
 18979            }
 980
 6981            Count = dictionary.Count;
 24982        }
 983
 984        /// <inheritdoc />
 985        protected override void OnPreStart()
 1270986        {
 1270987            ClearSubscribers();
 988
 1270989            if (!isReadOnly && clearOnStart)
 1252990            {
 1252991                dictionary.Clear();
 1252992                keys.Clear();
 1252993                values.Clear();
 1252994                Count = 0;
 1252995            }
 1270996        }
 997
 998        /// <summary>
 999        ///     Warns if there are any left-over subscribers to the events.
 1000        /// </summary>
 1001        /// <remarks>This will only be called in the Unity editor and builds with the DEBUG flag.</remarks>
 1002        protected override void WarnIfLeftOverSubscribers()
 12581003        {
 12581004            base.WarnIfLeftOverSubscribers();
 12581005            EventHelper.WarnIfLeftOverSubscribers(OnCollectionChanged, nameof(OnCollectionChanged), this);
 12581006        }
 1007
 1008        /// <summary>
 1009        ///     Warns if there are any left-over objects in the dictionary.
 1010        /// </summary>
 1011        /// <remarks>This will only be called in the Unity editor and builds with the DEBUG flag.</remarks>
 1012        [Conditional("DEBUG")]
 1013        protected void WarnIfLeftOverObjects()
 12521014        {
 12521015            if (!isReadOnly && clearOnStart && dictionary.Count > 0)
 61016            {
 61017                Debug.LogWarning($"There are left over objects in the scriptable dictionary {name}. You should clear the
 61018            }
 12521019        }
 1020
 1021        /// <summary>
 1022        ///     Removes any subscribers from the event.
 1023        /// </summary>
 1024        /// <param name="warnIfLeftOver">
 1025        ///     If true, a warning will be printed in the console if there are any subscribers.
 1026        ///     The warning will only be printed in the editor and debug builds.
 1027        /// </param>
 1028        public void ClearSubscribers(bool warnIfLeftOver = false)
 12761029        {
 1030#if DEBUG
 12761031            if (warnIfLeftOver)
 61032            {
 61033                WarnIfLeftOverSubscribers();
 61034            }
 1035#endif
 1036
 12761037            OnCollectionChanged = null;
 12761038            ClearBaseSubscribers();
 12761039        }
 1040
 1041        /// <inheritdoc />
 1042        protected override void OnDisabled()
 12521043        {
 12521044            WarnIfLeftOverObjects();
 12521045            WarnIfLeftOverSubscribers();
 1046
 12521047            dictionary.TrimExcess();
 12521048        }
 1049
 1050        #region Obsolete
 1051#if UNITY_EDITOR // Don't include in builds.
 1052        /// <summary>
 1053        ///     Called when an item was added. Gives you the key and value of the newly added item.
 1054        /// </summary>
 1055        [Obsolete("Use 'OnCollectionChanged' instead. This will be removed in build.", true)]
 1056#pragma warning disable CS0067 // Event is never used
 1057        public event Action<TKey, TValue>? OnAdded;
 1058        /// <summary>
 1059        ///     Called when an item was set. Gives you the key, the old value, and the new value of the item.
 1060        /// </summary>
 1061        [Obsolete("Use 'OnCollectionChanged' instead. This will be removed in build.", true)]
 1062        public event Action<TKey, TValue, TValue>? OnSet;
 1063        /// <summary>
 1064        ///     Called when an item was removed. Gives you the key and value of the removed item.
 1065        /// </summary>
 1066        [Obsolete("Use 'OnCollectionChanged' instead. This will be removed in build.", true)]
 1067        public event Action<TKey, TValue>? OnRemoved;
 1068        /// <summary>
 1069        ///     Called when the dictionary is cleared.
 1070        /// </summary>
 1071        [Obsolete("Use 'OnCollectionChanged' instead. This will be removed in build.", true)]
 1072        public event Action? OnCleared;
 1073        /// <summary>
 1074        ///     Called when the dictionary is changed in any way.
 1075        /// </summary>
 1076        [Obsolete("Use 'OnCollectionChanged' instead. This will be removed in build.", true)]
 1077        public event Action<DictionaryChangeType>? OnChanged;
 1078#pragma warning restore CS0067 // Event is never used
 1079#endif // UNITY_EDITOR
 1080        #endregion
 1081    }
 1082}

Methods/Properties

GetViewHashCode()
ScriptableDictionary()
get_Item(System.Object)
set_Item(System.Object, System.Object)
Item(TKey)
Item(TKey, TValue)
Comparer()
Comparer(System.Collections.Generic.IEqualityComparer[TKey])
Count()
Count(System.Int32)
IsReadOnly()
IsReadOnly(System.Boolean)
SetEqualityCheck()
SetEqualityCheck(System.Boolean)
ClearOnStart()
ClearOnStart(System.Boolean)
Keys()
Values()
get_IsFixedSize()
get_IsSynchronized()
get_SyncRoot()
get_Values()
get_Keys()
System.Collections.Generic.IDictionary<TKey,TValue>.get_Keys()
System.Collections.Generic.IDictionary<TKey,TValue>.get_Values()
System.Collections.Generic.IReadOnlyDictionary<TKey,TValue>.get_Keys()
System.Collections.Generic.IReadOnlyDictionary<TKey,TValue>.get_Values()
IsValid()
IsIndexUnique(System.Int32)
Add(TKey, TValue)
Add(System.Object, System.Object)
System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<TKey,TValue>>.Add(System.Collections.Generic.KeyValuePair[TKey,TValue])
AddInternal(TKey, TValue)
Clear()
ContainsKey(TKey)
ContainsValue(TValue)
Contains(System.Object)
System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<TKey,TValue>>.Contains(System.Collections.Generic.KeyValuePair[TKey,TValue])
CopyTo(System.Array, System.Int32)
System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<TKey,TValue>>.CopyTo(, System.Int32)
EnsureCapacity(System.Int32)
GetEnumerator()
GetEnumerator()
System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey,TValue>>.GetEnumerator()
GetEnumerator()
Remove(TKey)
Remove(TKey, )
Remove(System.Object)
System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<TKey,TValue>>.Remove(System.Collections.Generic.KeyValuePair[TKey,TValue])
RemoveInternal(TKey, )
SetValue(TKey, TValue)
TrimExcess()
TrimExcess(System.Int32)
TryAdd(TKey, TValue)
TryAddInternal(TKey, TValue)
TryFindKey(System.Predicate[TKey], )
TryFindValue(System.Predicate[TValue], )
TryGetValue(TKey, )
InvokeCollectionChanged(Hertzole.ScriptableValues.CollectionChangedArgs[KeyValuePair`2])
OnBeforeSerialize()
OnAfterDeserialize()
OnPreStart()
WarnIfLeftOverSubscribers()
WarnIfLeftOverObjects()
ClearSubscribers(System.Boolean)
OnDisabled()