From a6862adb7d6e910ade815a4fd88e0bca759b341b Mon Sep 17 00:00:00 2001 From: Santiago Fernandez Madero Date: Thu, 25 Apr 2019 16:12:35 -0700 Subject: [PATCH] Nullable: Comparers, Dictionary and Friends (dotnet/coreclr#23971) * Nullable: Comparers, Dictionary and Friends * Add object constraint to Dictionary * Fix warning from new compiler and annotating dictionary * PR Feedback Commit migrated from https://github.com/dotnet/coreclr/commit/ad38bf7164ecb3ecad102645e8a8381fa015f565 --- .../Collections/Generic/ArraySortHelper.CoreCLR.cs | 9 +- .../System/Collections/Generic/Comparer.CoreCLR.cs | 2 +- .../System/Collections/Generic/ComparerHelpers.cs | 13 +- .../Generic/EqualityComparer.CoreCLR.cs | 5 +- .../src/System/Exception.CoreCLR.cs | 2 +- .../src/System/StubHelpers.cs | 2 +- .../System.Private.CoreLib/src/System/Array.cs | 4 +- .../src/System/Collections/DictionaryEntry.cs | 9 +- .../System/Collections/Generic/ArraySortHelper.cs | 15 +- .../src/System/Collections/Generic/Comparer.cs | 17 +- .../src/System/Collections/Generic/Dictionary.cs | 227 +++++++++++---------- .../System/Collections/Generic/EqualityComparer.cs | 19 +- .../src/System/Collections/Generic/KeyValuePair.cs | 3 +- .../src/System/Collections/IDictionary.cs | 6 +- .../System/Collections/IDictionaryEnumerator.cs | 3 +- .../src/System/Collections/IEqualityComparer.cs | 5 +- .../src/System/Security/SecurityElement.cs | 2 +- .../System.Private.CoreLib/src/System/Tuple.cs | 28 +-- .../src/System/ValueTuple.cs | 92 ++++----- 19 files changed, 241 insertions(+), 222 deletions(-) diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Collections/Generic/ArraySortHelper.CoreCLR.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Collections/Generic/ArraySortHelper.CoreCLR.cs index 8bb5138..b992edf 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Collections/Generic/ArraySortHelper.CoreCLR.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Collections/Generic/ArraySortHelper.CoreCLR.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Globalization; using System.Runtime.CompilerServices; using System.Diagnostics; @@ -11,8 +12,8 @@ namespace System.Collections.Generic { internal interface IArraySortHelper { - void Sort(TKey[] keys, int index, int length, IComparer comparer); - int BinarySearch(TKey[] keys, int index, int length, TKey value, IComparer comparer); + void Sort(TKey[] keys, int index, int length, IComparer? comparer); + int BinarySearch(TKey[] keys, int index, int length, TKey value, IComparer? comparer); } [TypeDependencyAttribute("System.Collections.Generic.GenericArraySortHelper`1")] @@ -52,7 +53,7 @@ namespace System.Collections.Generic internal interface IArraySortHelper { - void Sort(TKey[] keys, TValue[] values, int index, int length, IComparer comparer); + void Sort(TKey[] keys, TValue[] values, int index, int length, IComparer? comparer); } [TypeDependencyAttribute("System.Collections.Generic.GenericArraySortHelper`2")] @@ -89,4 +90,4 @@ namespace System.Collections.Generic : IArraySortHelper { } -} \ No newline at end of file +} diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Collections/Generic/Comparer.CoreCLR.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Collections/Generic/Comparer.CoreCLR.cs index b06fe7e..62c5dba 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Collections/Generic/Comparer.CoreCLR.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Collections/Generic/Comparer.CoreCLR.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. - +#nullable enable using System.Runtime; using System.Runtime.CompilerServices; diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Collections/Generic/ComparerHelpers.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Collections/Generic/ComparerHelpers.cs index 4563bc1..a382ba6 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Collections/Generic/ComparerHelpers.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Collections/Generic/ComparerHelpers.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using static System.RuntimeTypeHandle; @@ -30,7 +31,7 @@ namespace System.Collections.Generic { Debug.Assert(type != null && type is RuntimeType); - object result = null; + object? result = null; var runtimeType = (RuntimeType)type; // If T implements IComparable return a GenericComparer @@ -60,7 +61,7 @@ namespace System.Collections.Generic /// Creates the default for a nullable type. /// /// The nullable type to create the default comparer for. - private static object TryCreateNullableComparer(RuntimeType nullableType) + private static object? TryCreateNullableComparer(RuntimeType nullableType) { Debug.Assert(nullableType != null); Debug.Assert(nullableType.IsGenericType && nullableType.GetGenericTypeDefinition() == typeof(Nullable<>)); @@ -79,7 +80,7 @@ namespace System.Collections.Generic /// Creates the default for an enum type. /// /// The enum type to create the default comparer for. - private static object TryCreateEnumComparer(RuntimeType enumType) + private static object? TryCreateEnumComparer(RuntimeType enumType) { Debug.Assert(enumType != null); Debug.Assert(enumType.IsEnum); @@ -118,7 +119,7 @@ namespace System.Collections.Generic { Debug.Assert(type != null && type is RuntimeType); - object result = null; + object? result = null; var runtimeType = (RuntimeType)type; // Specialize for byte so Array.IndexOf is faster. @@ -153,7 +154,7 @@ namespace System.Collections.Generic /// Creates the default for a nullable type. /// /// The nullable type to create the default equality comparer for. - private static object TryCreateNullableEqualityComparer(RuntimeType nullableType) + private static object? TryCreateNullableEqualityComparer(RuntimeType nullableType) { Debug.Assert(nullableType != null); Debug.Assert(nullableType.IsGenericType && nullableType.GetGenericTypeDefinition() == typeof(Nullable<>)); @@ -172,7 +173,7 @@ namespace System.Collections.Generic /// Creates the default for an enum type. /// /// The enum type to create the default equality comparer for. - private static object TryCreateEnumEqualityComparer(RuntimeType enumType) + private static object? TryCreateEnumEqualityComparer(RuntimeType enumType) { Debug.Assert(enumType != null); Debug.Assert(enumType.IsEnum); diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Collections/Generic/EqualityComparer.CoreCLR.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Collections/Generic/EqualityComparer.CoreCLR.cs index 8ef6818..5e35100 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Collections/Generic/EqualityComparer.CoreCLR.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Collections/Generic/EqualityComparer.CoreCLR.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime; using System.Runtime.CompilerServices; using System.Diagnostics; @@ -138,7 +139,7 @@ namespace System.Collections.Generic { for (int i = startIndex; i < endIndex; i++) { - if (array[i] != null && array[i].Equals(value)) return i; + if (array[i] != null && array[i]!.Equals(value)) return i; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34644 } } return -1; @@ -158,7 +159,7 @@ namespace System.Collections.Generic { for (int i = startIndex; i >= endIndex; i--) { - if (array[i] != null && array[i].Equals(value)) return i; + if (array[i] != null && array[i]!.Equals(value)) return i; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34644 } } return -1; diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Exception.CoreCLR.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Exception.CoreCLR.cs index 9faf292..480ef74 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Exception.CoreCLR.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Exception.CoreCLR.cs @@ -117,7 +117,7 @@ namespace System if (Data["__RestrictedErrorObject"] is __RestrictedErrorObject restrictedObject) restrictedErrorObject = restrictedObject.RealErrorObject; } - return (bool)Data["__HasRestrictedLanguageErrorObject"]; + return (bool)Data["__HasRestrictedLanguageErrorObject"]!; } return false; diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/StubHelpers.cs b/src/coreclr/src/System.Private.CoreLib/src/System/StubHelpers.cs index c1fc51c..763efbb 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/StubHelpers.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/StubHelpers.cs @@ -744,7 +744,7 @@ namespace System.StubHelpers } } - internal static unsafe void ConvertContentsToNative_KeyValuePair(ref KeyValuePair[]? managedArray, IntPtr pNativeHome) + internal static unsafe void ConvertContentsToNative_KeyValuePair(ref KeyValuePair[]? managedArray, IntPtr pNativeHome) { if (managedArray != null) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Array.cs b/src/libraries/System.Private.CoreLib/src/System/Array.cs index 2a4cd81..96ee9e3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Array.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Array.cs @@ -383,7 +383,7 @@ namespace System for (int i = (this.Length >= 8 ? this.Length - 8 : 0); i < this.Length; i++) { - ret = CombineHashCodes(ret, comparer!.GetHashCode(GetValue(i))); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + ret = CombineHashCodes(ret, comparer!.GetHashCode(GetValue(i)!)); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } return ret; @@ -1552,7 +1552,7 @@ namespace System ThrowHelper.ThrowArgumentNullException(ExceptionArgument.comparison); } - ArraySortHelper.Sort(array!, 0, array!.Length, comparison); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 + ArraySortHelper.Sort(array!, 0, array!.Length, comparison!); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } public static bool TrueForAll(T[] array, Predicate match) diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/DictionaryEntry.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/DictionaryEntry.cs index 187301a..b207022 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/DictionaryEntry.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/DictionaryEntry.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.ComponentModel; namespace System.Collections @@ -13,11 +14,11 @@ namespace System.Collections public struct DictionaryEntry { private object _key; // Do not rename (binary serialization) - private object _value; // Do not rename (binary serialization) + private object? _value; // Do not rename (binary serialization) // Constructs a new DictionaryEnumerator by setting the Key // and Value fields appropriately. - public DictionaryEntry(object key, object value) + public DictionaryEntry(object key, object? value) { _key = key; _value = value; @@ -36,7 +37,7 @@ namespace System.Collections } } - public object Value + public object? Value { get { @@ -50,7 +51,7 @@ namespace System.Collections } [EditorBrowsable(EditorBrowsableState.Never)] - public void Deconstruct(out object key, out object value) + public void Deconstruct(out object key, out object? value) { key = Key; value = Value; diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/ArraySortHelper.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/ArraySortHelper.cs index 03b9865..7d7d945 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/ArraySortHelper.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/ArraySortHelper.cs @@ -13,6 +13,7 @@ ** ===========================================================*/ +#nullable enable using System.Diagnostics; using System.Runtime.CompilerServices; @@ -38,7 +39,7 @@ namespace System.Collections.Generic return result; } - internal static void ThrowOrIgnoreBadComparer(object comparer) + internal static void ThrowOrIgnoreBadComparer(object? comparer) { throw new ArgumentException(SR.Format(SR.Arg_BogusIComparer, comparer)); } @@ -48,7 +49,7 @@ namespace System.Collections.Generic { #region IArraySortHelper Members - public void Sort(T[] keys, int index, int length, IComparer comparer) + public void Sort(T[] keys, int index, int length, IComparer? comparer) { Debug.Assert(keys != null, "Check the arguments in the caller!"); Debug.Assert(index >= 0 && length >= 0 && (keys.Length - index >= length), "Check the arguments in the caller!"); @@ -74,7 +75,7 @@ namespace System.Collections.Generic } } - public int BinarySearch(T[] array, int index, int length, T value, IComparer comparer) + public int BinarySearch(T[] array, int index, int length, T value, IComparer? comparer) { try { @@ -335,7 +336,7 @@ namespace System.Collections.Generic #region IArraySortHelper Members - public void Sort(T[] keys, int index, int length, IComparer comparer) + public void Sort(T[] keys, int index, int length, IComparer? comparer) { Debug.Assert(keys != null, "Check the arguments in the caller!"); Debug.Assert(index >= 0 && length >= 0 && (keys.Length - index >= length), "Check the arguments in the caller!"); @@ -361,7 +362,7 @@ namespace System.Collections.Generic } } - public int BinarySearch(T[] array, int index, int length, T value, IComparer comparer) + public int BinarySearch(T[] array, int index, int length, T value, IComparer? comparer) { Debug.Assert(array != null, "Check the arguments in the caller!"); Debug.Assert(index >= 0 && length >= 0 && (array.Length - index >= length), "Check the arguments in the caller!"); @@ -624,7 +625,7 @@ namespace System.Collections.Generic internal partial class ArraySortHelper { - public void Sort(TKey[] keys, TValue[] values, int index, int length, IComparer comparer) + public void Sort(TKey[] keys, TValue[] values, int index, int length, IComparer? comparer) { Debug.Assert(keys != null, "Check the arguments in the caller!"); // Precondition on interface method Debug.Assert(values != null, "Check the arguments in the caller!"); @@ -871,7 +872,7 @@ namespace System.Collections.Generic internal partial class GenericArraySortHelper where TKey : IComparable { - public void Sort(TKey[] keys, TValue[] values, int index, int length, IComparer comparer) + public void Sort(TKey[] keys, TValue[] values, int index, int length, IComparer? comparer) { Debug.Assert(keys != null, "Check the arguments in the caller!"); Debug.Assert(index >= 0 && length >= 0 && (keys.Length - index >= length), "Check the arguments in the caller!"); diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Comparer.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Comparer.cs index f7c6cf8..aa36769 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Comparer.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Comparer.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.CompilerServices; using System.Runtime.Serialization; @@ -21,9 +22,9 @@ namespace System.Collections.Generic return new ComparisonComparer(comparison); } - public abstract int Compare(T x, T y); + public abstract int Compare(T x, T y); // TODO-NULLABLE-GENERIC: x and y must be marked as nullable - int IComparer.Compare(object x, object y) + int IComparer.Compare(object? x, object? y) { if (x == null) return y == null ? 0 : -1; if (y == null) return 1; @@ -58,7 +59,7 @@ namespace System.Collections.Generic // Needs to be public to support binary serialization compatibility public sealed partial class GenericComparer : Comparer where T : IComparable { - public override int Compare(T x, T y) + public override int Compare(T x, T y) // TODO-NULLABLE-GENERIC: x and y must be marked as nullable { if (x != null) { @@ -70,7 +71,7 @@ namespace System.Collections.Generic } // Equals method for the comparer itself. - public override bool Equals(object obj) => + public override bool Equals(object? obj) => obj != null && GetType() == obj.GetType(); public override int GetHashCode() => @@ -94,7 +95,7 @@ namespace System.Collections.Generic } // Equals method for the comparer itself. - public override bool Equals(object obj) => + public override bool Equals(object? obj) => obj != null && GetType() == obj.GetType(); public override int GetHashCode() => @@ -106,13 +107,13 @@ namespace System.Collections.Generic // Needs to be public to support binary serialization compatibility public sealed partial class ObjectComparer : Comparer { - public override int Compare(T x, T y) + public override int Compare(T x, T y) // TODO-NULLABLE-GENERIC: x and y must be marked as nullable { return System.Collections.Comparer.Default.Compare(x, y); } // Equals method for the comparer itself. - public override bool Equals(object obj) => + public override bool Equals(object? obj) => obj != null && GetType() == obj.GetType(); public override int GetHashCode() => @@ -130,7 +131,7 @@ namespace System.Collections.Generic // public override int Compare(T x, T y) is runtime-specific // Equals method for the comparer itself. - public override bool Equals(object obj) => + public override bool Equals(object? obj) => obj != null && GetType() == obj.GetType(); public override int GetHashCode() => diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Dictionary.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Dictionary.cs index 0a36cb5..2744202 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Dictionary.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Dictionary.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.Serialization; @@ -33,7 +34,7 @@ namespace System.Collections.Generic [DebuggerDisplay("Count = {Count}")] [Serializable] [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] - public class Dictionary : IDictionary, IDictionary, IReadOnlyDictionary, ISerializable, IDeserializationCallback + public class Dictionary : IDictionary, IDictionary, IReadOnlyDictionary, ISerializable, IDeserializationCallback where TKey : object { private struct Entry { @@ -46,15 +47,15 @@ namespace System.Collections.Generic public TValue value; // Value of entry } - private int[] _buckets; - private Entry[] _entries; + private int[]? _buckets; + private Entry[]? _entries; private int _count; private int _freeList; private int _freeCount; private int _version; - private IEqualityComparer _comparer; - private KeyCollection _keys; - private ValueCollection _values; + private IEqualityComparer? _comparer; + private KeyCollection? _keys; + private ValueCollection? _values; private const int StartOfFreeList = -3; // constants for serialization @@ -67,9 +68,9 @@ namespace System.Collections.Generic public Dictionary(int capacity) : this(capacity, null) { } - public Dictionary(IEqualityComparer comparer) : this(0, comparer) { } + public Dictionary(IEqualityComparer? comparer) : this(0, comparer) { } - public Dictionary(int capacity, IEqualityComparer comparer) + public Dictionary(int capacity, IEqualityComparer? comparer) { if (capacity < 0) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.capacity); if (capacity > 0) Initialize(capacity); @@ -87,7 +88,7 @@ namespace System.Collections.Generic public Dictionary(IDictionary dictionary) : this(dictionary, null) { } - public Dictionary(IDictionary dictionary, IEqualityComparer comparer) : + public Dictionary(IDictionary dictionary, IEqualityComparer? comparer) : this(dictionary != null ? dictionary.Count : 0, comparer) { if (dictionary == null) @@ -99,14 +100,14 @@ namespace System.Collections.Generic // avoid the enumerator allocation and overhead by looping through the entries array directly. // We only do this when dictionary is Dictionary and not a subclass, to maintain // back-compat with subclasses that may have overridden the enumerator behavior. - if (dictionary.GetType() == typeof(Dictionary)) + if (dictionary!.GetType() == typeof(Dictionary)) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 { Dictionary d = (Dictionary)dictionary; int count = d._count; - Entry[] entries = d._entries; + Entry[]? entries = d._entries; for (int i = 0; i < count; i++) { - if (entries[i].next >= -1) + if (entries![i].next >= -1) { Add(entries[i].key, entries[i].value); } @@ -122,7 +123,7 @@ namespace System.Collections.Generic public Dictionary(IEnumerable> collection) : this(collection, null) { } - public Dictionary(IEnumerable> collection, IEqualityComparer comparer) : + public Dictionary(IEnumerable> collection, IEqualityComparer? comparer) : this((collection as ICollection>)?.Count ?? 0, comparer) { if (collection == null) @@ -130,7 +131,7 @@ namespace System.Collections.Generic ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection); } - foreach (KeyValuePair pair in collection) + foreach (KeyValuePair pair in collection!) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 { Add(pair.Key, pair.Value); } @@ -216,9 +217,9 @@ namespace System.Collections.Generic get { int i = FindEntry(key); - if (i >= 0) return _entries[i].value; + if (i >= 0) return _entries![i].value; ThrowHelper.ThrowKeyNotFoundException(key); - return default; + return default!; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 (annotating ThrowHelper removes this return statement). } set { @@ -239,7 +240,7 @@ namespace System.Collections.Generic bool ICollection>.Contains(KeyValuePair keyValuePair) { int i = FindEntry(keyValuePair.Key); - if (i >= 0 && EqualityComparer.Default.Equals(_entries[i].value, keyValuePair.Value)) + if (i >= 0 && EqualityComparer.Default.Equals(_entries![i].value, keyValuePair.Value)) { return true; } @@ -249,7 +250,7 @@ namespace System.Collections.Generic bool ICollection>.Remove(KeyValuePair keyValuePair) { int i = FindEntry(keyValuePair.Key); - if (i >= 0 && EqualityComparer.Default.Equals(_entries[i].value, keyValuePair.Value)) + if (i >= 0 && EqualityComparer.Default.Equals(_entries![i].value, keyValuePair.Value)) { Remove(keyValuePair.Key); return true; @@ -262,6 +263,9 @@ namespace System.Collections.Generic int count = _count; if (count > 0) { + Debug.Assert(_buckets != null, "_buckets should be non-null"); + Debug.Assert(_entries != null, "_entries should be non-null"); + Array.Clear(_buckets, 0, _buckets.Length); _count = 0; @@ -276,22 +280,22 @@ namespace System.Collections.Generic public bool ContainsValue(TValue value) { - Entry[] entries = _entries; + Entry[]? entries = _entries; if (value == null) { for (int i = 0; i < _count; i++) { - if (entries[i].next >= -1 && entries[i].value == null) return true; + if (entries![i].next >= -1 && entries[i].value == null) return true; } } else { - if (default(TValue) != null) + if (default(TValue)! != null) // TODO-NULLABLE-GENERIC: https://github.com/dotnet/roslyn/issues/34757 { // ValueType: Devirtualize with EqualityComparer.Default intrinsic for (int i = 0; i < _count; i++) { - if (entries[i].next >= -1 && EqualityComparer.Default.Equals(entries[i].value, value)) return true; + if (entries![i].next >= -1 && EqualityComparer.Default.Equals(entries[i].value, value)) return true; } } else @@ -302,7 +306,7 @@ namespace System.Collections.Generic EqualityComparer defaultComparer = EqualityComparer.Default; for (int i = 0; i < _count; i++) { - if (entries[i].next >= -1 && defaultComparer.Equals(entries[i].value, value)) return true; + if (entries![i].next >= -1 && defaultComparer.Equals(entries[i].value, value)) return true; } } } @@ -316,7 +320,7 @@ namespace System.Collections.Generic ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); } - if ((uint)index > (uint)array.Length) + if ((uint)index > (uint)array!.Length) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 { ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); } @@ -327,10 +331,10 @@ namespace System.Collections.Generic } int count = _count; - Entry[] entries = _entries; + Entry[]? entries = _entries; for (int i = 0; i < count; i++) { - if (entries[i].next >= -1) + if (entries![i].next >= -1) { array[index++] = new KeyValuePair(entries[i].key, entries[i].value); } @@ -350,7 +354,7 @@ namespace System.Collections.Generic ThrowHelper.ThrowArgumentNullException(ExceptionArgument.info); } - info.AddValue(VersionName, _version); + info!.AddValue(VersionName, _version); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 info.AddValue(ComparerName, _comparer ?? EqualityComparer.Default, typeof(IEqualityComparer)); info.AddValue(HashSizeName, _buckets == null ? 0 : _buckets.Length); // This is the length of the bucket array @@ -370,18 +374,19 @@ namespace System.Collections.Generic } int i = -1; - int[] buckets = _buckets; - Entry[] entries = _entries; + int[]? buckets = _buckets; + Entry[]? entries = _entries; int collisionCount = 0; if (buckets != null) { - IEqualityComparer comparer = _comparer; + Debug.Assert(entries != null, "expected entries to be != null"); + IEqualityComparer? comparer = _comparer; if (comparer == null) { - uint hashCode = (uint)key.GetHashCode(); + uint hashCode = (uint)key!.GetHashCode(); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 // Value in _buckets is 1-based i = buckets[hashCode % (uint)buckets.Length] - 1; - if (default(TKey) != null) + if (default(TKey)! != null) // TODO-NULLABLE-GENERIC: https://github.com/dotnet/roslyn/issues/34757 { // ValueType: Devirtualize with EqualityComparer.Default intrinsic do @@ -482,19 +487,20 @@ namespace System.Collections.Generic Initialize(0); } - Entry[] entries = _entries; - IEqualityComparer comparer = _comparer; + Entry[]? entries = _entries; + Debug.Assert(entries != null, "expected entries to be non-null"); - uint hashCode = (uint)((comparer == null) ? key.GetHashCode() : comparer.GetHashCode(key)); + IEqualityComparer? comparer = _comparer; + uint hashCode = (uint)((comparer == null) ? key!.GetHashCode() : comparer.GetHashCode(key)); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 int collisionCount = 0; - ref int bucket = ref _buckets[hashCode % (uint)_buckets.Length]; + ref int bucket = ref _buckets![hashCode % (uint)_buckets.Length]; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 (Initialize inits sets _buckets to non null) // Value in _buckets is 1-based int i = bucket - 1; if (comparer == null) { - if (default(TKey) != null) + if (default(TKey)! != null) // TODO-NULLABLE-GENERIC: https://github.com/dotnet/roslyn/issues/34757 { // ValueType: Devirtualize with EqualityComparer.Default intrinsic do @@ -637,7 +643,7 @@ namespace System.Collections.Generic entries = _entries; } - ref Entry entry = ref entries[index]; + ref Entry entry = ref entries![index]; if (updateFreeList) { @@ -655,7 +661,7 @@ namespace System.Collections.Generic _version++; // Value types never rehash - if (default(TKey) == null && collisionCount > HashHelpers.HashCollisionThreshold && comparer is NonRandomizedStringEqualityComparer) + if (default(TKey)! == null && collisionCount > HashHelpers.HashCollisionThreshold && comparer is NonRandomizedStringEqualityComparer) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757 { // If we hit the collision threshold we'll need to switch to the comparer which is using randomized string hashing // i.e. EqualityComparer.Default. @@ -679,13 +685,13 @@ namespace System.Collections.Generic int realVersion = siInfo.GetInt32(VersionName); int hashsize = siInfo.GetInt32(HashSizeName); - _comparer = (IEqualityComparer)siInfo.GetValue(ComparerName, typeof(IEqualityComparer)); + _comparer = (IEqualityComparer)siInfo.GetValue(ComparerName, typeof(IEqualityComparer))!; // When serialized if comparer is null, we use the default. if (hashsize != 0) { Initialize(hashsize); - KeyValuePair[] array = (KeyValuePair[]) + KeyValuePair[]? array = (KeyValuePair[]?) siInfo.GetValue(KeyValuePairsName, typeof(KeyValuePair[])); if (array == null) @@ -693,7 +699,7 @@ namespace System.Collections.Generic ThrowHelper.ThrowSerializationException(ExceptionResource.Serialization_MissingKeys); } - for (int i = 0; i < array.Length; i++) + for (int i = 0; i < array!.Length; i++) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 { if (array[i].Key == null) { @@ -717,7 +723,8 @@ namespace System.Collections.Generic private void Resize(int newSize, bool forceNewHashCodes) { // Value types never rehash - Debug.Assert(!forceNewHashCodes || default(TKey) == null); + Debug.Assert(!forceNewHashCodes || default(TKey)! == null); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757 + Debug.Assert(_entries != null, "_entries should be non-null"); Debug.Assert(newSize >= _entries.Length); int[] buckets = new int[newSize]; @@ -726,7 +733,7 @@ namespace System.Collections.Generic int count = _count; Array.Copy(_entries, 0, entries, 0, count); - if (default(TKey) == null && forceNewHashCodes) + if (default(TKey)! == null && forceNewHashCodes) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757 { for (int i = 0; i < count; i++) { @@ -764,12 +771,13 @@ namespace System.Collections.Generic ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); } - int[] buckets = _buckets; - Entry[] entries = _entries; + int[]? buckets = _buckets; + Entry[]? entries = _entries; int collisionCount = 0; if (buckets != null) { - uint hashCode = (uint)(_comparer?.GetHashCode(key) ?? key.GetHashCode()); + Debug.Assert(entries != null, "entries should be non-null"); + uint hashCode = (uint)(_comparer?.GetHashCode(key) ?? key!.GetHashCode()); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 uint bucket = hashCode % (uint)buckets.Length; int last = -1; // Value in buckets is 1-based @@ -796,11 +804,11 @@ namespace System.Collections.Generic if (RuntimeHelpers.IsReferenceOrContainsReferences()) { - entry.key = default; + entry.key = default!; // TODO-NULLABLE-GENERIC } if (RuntimeHelpers.IsReferenceOrContainsReferences()) { - entry.value = default; + entry.value = default!; // TODO-NULLABLE-GENERIC } _freeList = i; _freeCount++; @@ -824,19 +832,20 @@ namespace System.Collections.Generic // This overload is a copy of the overload Remove(TKey key) with one additional // statement to copy the value for entry being removed into the output parameter. // Code has been intentionally duplicated for performance reasons. - public bool Remove(TKey key, out TValue value) + public bool Remove(TKey key, out TValue value) // TODO-NULLABLE-GENERIC: https://github.com/dotnet/roslyn/issues/26761 { if (key == null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key); } - int[] buckets = _buckets; - Entry[] entries = _entries; + int[]? buckets = _buckets; + Entry[]? entries = _entries; int collisionCount = 0; if (buckets != null) { - uint hashCode = (uint)(_comparer?.GetHashCode(key) ?? key.GetHashCode()); + Debug.Assert(entries != null, "entries should be non-null"); + uint hashCode = (uint)(_comparer?.GetHashCode(key) ?? key!.GetHashCode()); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 uint bucket = hashCode % (uint)buckets.Length; int last = -1; // Value in buckets is 1-based @@ -865,11 +874,11 @@ namespace System.Collections.Generic if (RuntimeHelpers.IsReferenceOrContainsReferences()) { - entry.key = default; + entry.key = default!; // TODO-NULLABLE-GENERIC } if (RuntimeHelpers.IsReferenceOrContainsReferences()) { - entry.value = default; + entry.value = default!; // TODO-NULLABLE-GENERIC } _freeList = i; _freeCount++; @@ -887,19 +896,19 @@ namespace System.Collections.Generic collisionCount++; } } - value = default; + value = default!; // TODO-NULLABLE-GENERIC return false; } - public bool TryGetValue(TKey key, out TValue value) + public bool TryGetValue(TKey key, out TValue value) // TODO-NULLABLE-GENERIC: https://github.com/dotnet/roslyn/issues/26761 { int i = FindEntry(key); if (i >= 0) { - value = _entries[i].value; + value = _entries![i].value; return true; } - value = default; + value = default!; // TODO-NULLABLE-GENERIC return false; } @@ -915,7 +924,7 @@ namespace System.Collections.Generic { if (array == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); - if (array.Rank != 1) + if (array!.Rank != 1) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported); if (array.GetLowerBound(0) != 0) ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound); @@ -930,10 +939,10 @@ namespace System.Collections.Generic } else if (array is DictionaryEntry[] dictEntryArray) { - Entry[] entries = _entries; + Entry[]? entries = _entries; for (int i = 0; i < _count; i++) { - if (entries[i].next >= -1) + if (entries![i].next >= -1) { dictEntryArray[index++] = new DictionaryEntry(entries[i].key, entries[i].value); } @@ -941,7 +950,7 @@ namespace System.Collections.Generic } else { - object[] objects = array as object[]; + object[]? objects = array as object[]; if (objects == null) { ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType(); @@ -950,12 +959,12 @@ namespace System.Collections.Generic try { int count = _count; - Entry[] entries = _entries; + Entry[]? entries = _entries; for (int i = 0; i < count; i++) { - if (entries[i].next >= -1) + if (entries![i].next >= -1) { - objects[index++] = new KeyValuePair(entries[i].key, entries[i].value); + objects![index++] = new KeyValuePair(entries[i].key, entries[i].value); // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 } } } @@ -1013,7 +1022,7 @@ namespace System.Collections.Generic ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.capacity); int newSize = HashHelpers.GetPrime(capacity); - Entry[] oldEntries = _entries; + Entry[]? oldEntries = _entries; int currentCapacity = oldEntries == null ? 0 : oldEntries.Length; if (newSize >= currentCapacity) return; @@ -1021,19 +1030,19 @@ namespace System.Collections.Generic int oldCount = _count; _version++; Initialize(newSize); - Entry[] entries = _entries; - int[] buckets = _buckets; + Entry[]? entries = _entries; + int[]? buckets = _buckets; int count = 0; for (int i = 0; i < oldCount; i++) { - uint hashCode = oldEntries[i].hashCode; + uint hashCode = oldEntries![i].hashCode; // At this point, we know we have entries. if (oldEntries[i].next >= -1) { - ref Entry entry = ref entries[count]; + ref Entry entry = ref entries![count]; entry = oldEntries[i]; uint bucket = hashCode % (uint)newSize; // Value in _buckets is 1-based - entry.next = buckets[bucket] - 1; + entry.next = buckets![bucket] - 1; // If we get here, we have entries, therefore buckets is not null. // Value in _buckets is 1-based buckets[bucket] = count + 1; count++; @@ -1055,7 +1064,7 @@ namespace System.Collections.Generic ICollection IDictionary.Values => (ICollection)Values; - object IDictionary.this[object key] + object? IDictionary.this[object key] // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2384 { get { @@ -1064,7 +1073,7 @@ namespace System.Collections.Generic int i = FindEntry((TKey)key); if (i >= 0) { - return _entries[i].value; + return _entries![i].value; } } return null; @@ -1079,10 +1088,10 @@ namespace System.Collections.Generic try { - TKey tempKey = (TKey)key; + TKey tempKey = (TKey)key!; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 try { - this[tempKey] = (TValue)value; + this[tempKey] = (TValue)value!; } catch (InvalidCastException) { @@ -1105,7 +1114,7 @@ namespace System.Collections.Generic return (key is TKey); } - void IDictionary.Add(object key, object value) + void IDictionary.Add(object key, object? value) { if (key == null) { @@ -1115,11 +1124,11 @@ namespace System.Collections.Generic try { - TKey tempKey = (TKey)key; + TKey tempKey = (TKey)key!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 try { - Add(tempKey, (TValue)value); + Add(tempKey, (TValue)value!); } catch (InvalidCastException) { @@ -1185,7 +1194,7 @@ namespace System.Collections.Generic // dictionary.count+1 could be negative if dictionary.count is int.MaxValue while ((uint)_index < (uint)_dictionary._count) { - ref Entry entry = ref _dictionary._entries[_index++]; + ref Entry entry = ref _dictionary._entries![_index++]; if (entry.next >= -1) { @@ -1205,7 +1214,7 @@ namespace System.Collections.Generic { } - object IEnumerator.Current + object? IEnumerator.Current // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268 { get { @@ -1262,7 +1271,7 @@ namespace System.Collections.Generic } } - object IDictionaryEnumerator.Value + object? IDictionaryEnumerator.Value { get { @@ -1288,7 +1297,7 @@ namespace System.Collections.Generic { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.dictionary); } - _dictionary = dictionary; + _dictionary = dictionary!; // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 } public Enumerator GetEnumerator() @@ -1301,21 +1310,21 @@ namespace System.Collections.Generic ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); } - if (index < 0 || index > array.Length) + if (index < 0 || index > array!.Length) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 { ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); } - if (array.Length - index < _dictionary.Count) + if (array!.Length - index < _dictionary.Count) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 { ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall); } int count = _dictionary._count; - Entry[] entries = _dictionary._entries; + Entry[]? entries = _dictionary._entries; for (int i = 0; i < count; i++) { - if (entries[i].next >= -1) array[index++] = entries[i].key; + if (entries![i].next >= -1) array[index++] = entries[i].key; } } @@ -1348,7 +1357,7 @@ namespace System.Collections.Generic { if (array == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); - if (array.Rank != 1) + if (array!.Rank != 1) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/26761 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported); if (array.GetLowerBound(0) != 0) ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound); @@ -1363,19 +1372,19 @@ namespace System.Collections.Generic } else { - object[] objects = array as object[]; + object[]? objects = array as object[]; if (objects == null) { ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType(); } int count = _dictionary._count; - Entry[] entries = _dictionary._entries; + Entry[]? entries = _dictionary._entries; try { for (int i = 0; i < count; i++) { - if (entries[i].next >= -1) objects[index++] = entries[i].key; + if (entries![i].next >= -1) objects![index++] = entries[i].key; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 (objects) } } catch (ArrayTypeMismatchException) @@ -1401,7 +1410,7 @@ namespace System.Collections.Generic _dictionary = dictionary; _version = dictionary._version; _index = 0; - _currentKey = default; + _currentKey = default!; // TODO-NULLABLE-GENERIC } public void Dispose() @@ -1417,7 +1426,7 @@ namespace System.Collections.Generic while ((uint)_index < (uint)_dictionary._count) { - ref Entry entry = ref _dictionary._entries[_index++]; + ref Entry entry = ref _dictionary._entries![_index++]; if (entry.next >= -1) { @@ -1427,13 +1436,13 @@ namespace System.Collections.Generic } _index = _dictionary._count + 1; - _currentKey = default; + _currentKey = default!; // TODO-NULLABLE-GENERIC return false; } public TKey Current => _currentKey; - object IEnumerator.Current + object? IEnumerator.Current // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/23268 { get { @@ -1454,7 +1463,7 @@ namespace System.Collections.Generic } _index = 0; - _currentKey = default; + _currentKey = default!; // TODO-NULLABLE-GENERIC } } } @@ -1471,7 +1480,7 @@ namespace System.Collections.Generic { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.dictionary); } - _dictionary = dictionary; + _dictionary = dictionary!; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } public Enumerator GetEnumerator() @@ -1484,7 +1493,7 @@ namespace System.Collections.Generic ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); } - if (index < 0 || index > array.Length) + if ((uint)index > array!.Length) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 { ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException(); } @@ -1495,10 +1504,10 @@ namespace System.Collections.Generic } int count = _dictionary._count; - Entry[] entries = _dictionary._entries; + Entry[]? entries = _dictionary._entries; for (int i = 0; i < count; i++) { - if (entries[i].next >= -1) array[index++] = entries[i].value; + if (entries![i].next >= -1) array[index++] = entries[i].value; } } @@ -1531,7 +1540,7 @@ namespace System.Collections.Generic { if (array == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); - if (array.Rank != 1) + if (array!.Rank != 1) // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported); if (array.GetLowerBound(0) != 0) ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound); @@ -1546,19 +1555,19 @@ namespace System.Collections.Generic } else { - object[] objects = array as object[]; + object[]? objects = array as object[]; if (objects == null) { ThrowHelper.ThrowArgumentException_Argument_InvalidArrayType(); } int count = _dictionary._count; - Entry[] entries = _dictionary._entries; + Entry[]? entries = _dictionary._entries; try { for (int i = 0; i < count; i++) { - if (entries[i].next >= -1) objects[index++] = entries[i].value; + if (entries![i].next >= -1) objects![index++] = entries[i].value!; // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538 } } catch (ArrayTypeMismatchException) @@ -1584,7 +1593,7 @@ namespace System.Collections.Generic _dictionary = dictionary; _version = dictionary._version; _index = 0; - _currentValue = default; + _currentValue = default!; // TODO-NULLABLE-GENERIC } public void Dispose() @@ -1600,7 +1609,7 @@ namespace System.Collections.Generic while ((uint)_index < (uint)_dictionary._count) { - ref Entry entry = ref _dictionary._entries[_index++]; + ref Entry entry = ref _dictionary._entries![_index++]; if (entry.next >= -1) { @@ -1609,13 +1618,13 @@ namespace System.Collections.Generic } } _index = _dictionary._count + 1; - _currentValue = default; + _currentValue = default!; // TODO-NULLABLE-GENERIC return false; } public TValue Current => _currentValue; - object IEnumerator.Current + object? IEnumerator.Current { get { @@ -1635,7 +1644,7 @@ namespace System.Collections.Generic ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion(); } _index = 0; - _currentValue = default; + _currentValue = default!; // TODO-NULLABLE-GENERIC } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/EqualityComparer.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/EqualityComparer.cs index 0120477..fdaf3bc 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/EqualityComparer.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/EqualityComparer.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.Runtime.CompilerServices; using System.Runtime.Serialization; @@ -14,9 +15,11 @@ namespace System.Collections.Generic // public static EqualityComparer Default is runtime-specific public abstract bool Equals(T x, T y); - public abstract int GetHashCode(T obj); + public abstract int GetHashCode(T obj); // TODO-NULLABLE-GENERIC: Shouldn't accept nulls. - int IEqualityComparer.GetHashCode(object obj) +#pragma warning disable CS8617 // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/30958 + int IEqualityComparer.GetHashCode(object? obj) +#pragma warning restore CS8617 { if (obj == null) return 0; if (obj is T) return GetHashCode((T)obj); @@ -24,7 +27,7 @@ namespace System.Collections.Generic return 0; } - bool IEqualityComparer.Equals(object x, object y) + bool IEqualityComparer.Equals(object? x, object? y) { if (x == y) return true; if (x == null || y == null) return false; @@ -58,7 +61,7 @@ namespace System.Collections.Generic // Equals method for the comparer itself. // If in the future this type is made sealed, change the is check to obj != null && GetType() == obj.GetType(). - public override bool Equals(object obj) => + public override bool Equals(object? obj) => obj is GenericEqualityComparer; // If in the future this type is made sealed, change typeof(...) to GetType(). @@ -87,7 +90,7 @@ namespace System.Collections.Generic public override int GetHashCode(T? obj) => obj.GetHashCode(); // Equals method for the comparer itself. - public override bool Equals(object obj) => + public override bool Equals(object? obj) => obj != null && GetType() == obj.GetType(); public override int GetHashCode() => @@ -115,7 +118,7 @@ namespace System.Collections.Generic public override int GetHashCode(T obj) => obj?.GetHashCode() ?? 0; // Equals method for the comparer itself. - public override bool Equals(object obj) => + public override bool Equals(object? obj) => obj != null && GetType() == obj.GetType(); public override int GetHashCode() => @@ -140,7 +143,7 @@ namespace System.Collections.Generic } // Equals method for the comparer itself. - public override bool Equals(object obj) => + public override bool Equals(object? obj) => obj != null && GetType() == obj.GetType(); public override int GetHashCode() => @@ -174,7 +177,7 @@ namespace System.Collections.Generic } // Equals method for the comparer itself. - public override bool Equals(object obj) => + public override bool Equals(object? obj) => obj != null && GetType() == obj.GetType(); public override int GetHashCode() => diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/KeyValuePair.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/KeyValuePair.cs index 82c786d..18b3863 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/KeyValuePair.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/KeyValuePair.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable using System.ComponentModel; using System.Text; @@ -19,7 +20,7 @@ namespace System.Collections.Generic /// /// Used by KeyValuePair.ToString to reduce generic code /// - internal static string PairToString(object key, object value) + internal static string PairToString(object? key, object? value) { StringBuilder s = StringBuilderCache.Acquire(); s.Append('['); diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/IDictionary.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/IDictionary.cs index b077c91..3ecf669 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/IDictionary.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/IDictionary.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; +#nullable enable namespace System.Collections { @@ -15,7 +15,7 @@ namespace System.Collections // Interfaces are not serializable // The Item property provides methods to read and edit entries // in the Dictionary. - object this[object key] + object? this[object key] // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/2384 { get; set; @@ -39,7 +39,7 @@ namespace System.Collections // Adds a key-value pair to the dictionary. // - void Add(object key, object value); + void Add(object key, object? value); // Removes all pairs from the dictionary. void Clear(); diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/IDictionaryEnumerator.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/IDictionaryEnumerator.cs index 0cf6aaa..59b6f78 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/IDictionaryEnumerator.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/IDictionaryEnumerator.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#nullable enable namespace System.Collections { // This interface represents an enumerator that allows sequential access to the @@ -50,7 +51,7 @@ namespace System.Collections // to GetValue with no intervening calls to GetNext will // return the same object. // - object Value + object? Value { get; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/IEqualityComparer.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/IEqualityComparer.cs index 9b54768..c2c290c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/IEqualityComparer.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/IEqualityComparer.cs @@ -2,15 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System; - +#nullable enable namespace System.Collections { // An IEqualityComparer is a mechanism to consume custom performant comparison infrastructure // that can be consumed by some of the common collections. public interface IEqualityComparer { - bool Equals(object x, object y); + bool Equals(object? x, object? y); int GetHashCode(object obj); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Security/SecurityElement.cs b/src/libraries/System.Private.CoreLib/src/System/Security/SecurityElement.cs index 05c13c8..197eaa0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Security/SecurityElement.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Security/SecurityElement.cs @@ -145,7 +145,7 @@ namespace System.Security while (enumerator.MoveNext()) { string attrName = (string)enumerator.Key; - string attrValue = (string)enumerator.Value; + string? attrValue = (string?)enumerator.Value; if (!IsValidAttributeName(attrName)) throw new ArgumentException(SR.Format(SR.Argument_InvalidElementName, attrName)); diff --git a/src/libraries/System.Private.CoreLib/src/System/Tuple.cs b/src/libraries/System.Private.CoreLib/src/System/Tuple.cs index cf99600..bcfd4ce 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Tuple.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Tuple.cs @@ -157,7 +157,7 @@ namespace System int IStructuralEquatable.GetHashCode(IEqualityComparer comparer) { - return comparer.GetHashCode(m_Item1); + return comparer.GetHashCode(m_Item1!); // TODO-NULLABLE-GENERIC } int ITupleInternal.GetHashCode(IEqualityComparer comparer) @@ -262,7 +262,7 @@ namespace System int IStructuralEquatable.GetHashCode(IEqualityComparer comparer) { - return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1), comparer.GetHashCode(m_Item2)); + return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1!), comparer.GetHashCode(m_Item2!)); // TODO-NULLABLE-GENERIC } int ITupleInternal.GetHashCode(IEqualityComparer comparer) @@ -380,7 +380,7 @@ namespace System int IStructuralEquatable.GetHashCode(IEqualityComparer comparer) { - return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1), comparer.GetHashCode(m_Item2), comparer.GetHashCode(m_Item3)); + return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1!), comparer.GetHashCode(m_Item2!), comparer.GetHashCode(m_Item3!)); // TODO-NULLABLE-GENERIC } int ITupleInternal.GetHashCode(IEqualityComparer comparer) @@ -509,7 +509,7 @@ namespace System int IStructuralEquatable.GetHashCode(IEqualityComparer comparer) { - return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1), comparer.GetHashCode(m_Item2), comparer.GetHashCode(m_Item3), comparer.GetHashCode(m_Item4)); + return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1!), comparer.GetHashCode(m_Item2!), comparer.GetHashCode(m_Item3!), comparer.GetHashCode(m_Item4!)); // TODO-NULLABLE-GENERIC } int ITupleInternal.GetHashCode(IEqualityComparer comparer) @@ -649,7 +649,7 @@ namespace System int IStructuralEquatable.GetHashCode(IEqualityComparer comparer) { - return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1), comparer.GetHashCode(m_Item2), comparer.GetHashCode(m_Item3), comparer.GetHashCode(m_Item4), comparer.GetHashCode(m_Item5)); + return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1!), comparer.GetHashCode(m_Item2!), comparer.GetHashCode(m_Item3!), comparer.GetHashCode(m_Item4!), comparer.GetHashCode(m_Item5!)); // TODO-NULLABLE-GENERIC } int ITupleInternal.GetHashCode(IEqualityComparer comparer) @@ -800,7 +800,7 @@ namespace System int IStructuralEquatable.GetHashCode(IEqualityComparer comparer) { - return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1), comparer.GetHashCode(m_Item2), comparer.GetHashCode(m_Item3), comparer.GetHashCode(m_Item4), comparer.GetHashCode(m_Item5), comparer.GetHashCode(m_Item6)); + return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1!), comparer.GetHashCode(m_Item2!), comparer.GetHashCode(m_Item3!), comparer.GetHashCode(m_Item4!), comparer.GetHashCode(m_Item5!), comparer.GetHashCode(m_Item6!)); // TODO-NULLABLE-GENERIC } int ITupleInternal.GetHashCode(IEqualityComparer comparer) @@ -962,7 +962,7 @@ namespace System int IStructuralEquatable.GetHashCode(IEqualityComparer comparer) { - return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1), comparer.GetHashCode(m_Item2), comparer.GetHashCode(m_Item3), comparer.GetHashCode(m_Item4), comparer.GetHashCode(m_Item5), comparer.GetHashCode(m_Item6), comparer.GetHashCode(m_Item7)); + return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1!), comparer.GetHashCode(m_Item2!), comparer.GetHashCode(m_Item3!), comparer.GetHashCode(m_Item4!), comparer.GetHashCode(m_Item5!), comparer.GetHashCode(m_Item6!), comparer.GetHashCode(m_Item7!)); // TODO-NULLABLE-GENERIC } int ITupleInternal.GetHashCode(IEqualityComparer comparer) @@ -1149,19 +1149,19 @@ namespace System switch (k) { case 1: - return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item7), t.GetHashCode(comparer)); + return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item7!), t.GetHashCode(comparer)); // TODO-NULLABLE-GENERIC case 2: - return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item6), comparer.GetHashCode(m_Item7), t.GetHashCode(comparer)); + return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item6!), comparer.GetHashCode(m_Item7!), t.GetHashCode(comparer)); // TODO-NULLABLE-GENERIC case 3: - return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item5), comparer.GetHashCode(m_Item6), comparer.GetHashCode(m_Item7), t.GetHashCode(comparer)); + return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item5!), comparer.GetHashCode(m_Item6!), comparer.GetHashCode(m_Item7!), t.GetHashCode(comparer)); // TODO-NULLABLE-GENERIC case 4: - return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item4), comparer.GetHashCode(m_Item5), comparer.GetHashCode(m_Item6), comparer.GetHashCode(m_Item7), t.GetHashCode(comparer)); + return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item4!), comparer.GetHashCode(m_Item5!), comparer.GetHashCode(m_Item6!), comparer.GetHashCode(m_Item7!), t.GetHashCode(comparer)); // TODO-NULLABLE-GENERIC case 5: - return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item3), comparer.GetHashCode(m_Item4), comparer.GetHashCode(m_Item5), comparer.GetHashCode(m_Item6), comparer.GetHashCode(m_Item7), t.GetHashCode(comparer)); + return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item3!), comparer.GetHashCode(m_Item4!), comparer.GetHashCode(m_Item5!), comparer.GetHashCode(m_Item6!), comparer.GetHashCode(m_Item7!), t.GetHashCode(comparer)); // TODO-NULLABLE-GENERIC case 6: - return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item2), comparer.GetHashCode(m_Item3), comparer.GetHashCode(m_Item4), comparer.GetHashCode(m_Item5), comparer.GetHashCode(m_Item6), comparer.GetHashCode(m_Item7), t.GetHashCode(comparer)); + return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item2!), comparer.GetHashCode(m_Item3!), comparer.GetHashCode(m_Item4!), comparer.GetHashCode(m_Item5!), comparer.GetHashCode(m_Item6!), comparer.GetHashCode(m_Item7!), t.GetHashCode(comparer)); // TODO-NULLABLE-GENERIC case 7: - return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1), comparer.GetHashCode(m_Item2), comparer.GetHashCode(m_Item3), comparer.GetHashCode(m_Item4), comparer.GetHashCode(m_Item5), comparer.GetHashCode(m_Item6), comparer.GetHashCode(m_Item7), t.GetHashCode(comparer)); + return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1!), comparer.GetHashCode(m_Item2!), comparer.GetHashCode(m_Item3!), comparer.GetHashCode(m_Item4!), comparer.GetHashCode(m_Item5!), comparer.GetHashCode(m_Item6!), comparer.GetHashCode(m_Item7!), t.GetHashCode(comparer)); // TODO-NULLABLE-GENERIC } Debug.Fail("Missed all cases for computing Tuple hash code"); return -1; diff --git a/src/libraries/System.Private.CoreLib/src/System/ValueTuple.cs b/src/libraries/System.Private.CoreLib/src/System/ValueTuple.cs index 0fd476e..b227535 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ValueTuple.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ValueTuple.cs @@ -412,12 +412,12 @@ namespace System int IStructuralEquatable.GetHashCode(IEqualityComparer comparer) { - return comparer.GetHashCode(Item1); + return comparer.GetHashCode(Item1!); // TODO-NULLABLE-GENERIC } int IValueTupleInternal.GetHashCode(IEqualityComparer comparer) { - return comparer.GetHashCode(Item1); + return comparer.GetHashCode(Item1!); // TODO-NULLABLE-GENERIC } /// @@ -616,8 +616,8 @@ namespace System private int GetHashCodeCore(IEqualityComparer comparer) { - return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1), - comparer.GetHashCode(Item2)); + return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1!), + comparer.GetHashCode(Item2!)); // TODO-NULLABLE-GENERIC } int IValueTupleInternal.GetHashCode(IEqualityComparer comparer) @@ -823,9 +823,9 @@ namespace System private int GetHashCodeCore(IEqualityComparer comparer) { - return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1), - comparer.GetHashCode(Item2), - comparer.GetHashCode(Item3)); + return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1!), + comparer.GetHashCode(Item2!), + comparer.GetHashCode(Item3!)); // TODO-NULLABLE-GENERIC } int IValueTupleInternal.GetHashCode(IEqualityComparer comparer) @@ -1047,10 +1047,10 @@ namespace System private int GetHashCodeCore(IEqualityComparer comparer) { - return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1), - comparer.GetHashCode(Item2), - comparer.GetHashCode(Item3), - comparer.GetHashCode(Item4)); + return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1!), + comparer.GetHashCode(Item2!), + comparer.GetHashCode(Item3!), + comparer.GetHashCode(Item4!)); // TODO-NULLABLE-GENERIC } int IValueTupleInternal.GetHashCode(IEqualityComparer comparer) @@ -1290,11 +1290,11 @@ namespace System private int GetHashCodeCore(IEqualityComparer comparer) { - return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1), - comparer.GetHashCode(Item2), - comparer.GetHashCode(Item3), - comparer.GetHashCode(Item4), - comparer.GetHashCode(Item5)); + return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1!), + comparer.GetHashCode(Item2!), + comparer.GetHashCode(Item3!), + comparer.GetHashCode(Item4!), + comparer.GetHashCode(Item5!)); // TODO-NULLABLE-GENERIC } int IValueTupleInternal.GetHashCode(IEqualityComparer comparer) @@ -1552,12 +1552,12 @@ namespace System private int GetHashCodeCore(IEqualityComparer comparer) { - return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1), - comparer.GetHashCode(Item2), - comparer.GetHashCode(Item3), - comparer.GetHashCode(Item4), - comparer.GetHashCode(Item5), - comparer.GetHashCode(Item6)); + return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1!), + comparer.GetHashCode(Item2!), + comparer.GetHashCode(Item3!), + comparer.GetHashCode(Item4!), + comparer.GetHashCode(Item5!), + comparer.GetHashCode(Item6!)); // TODO-NULLABLE-GENERIC } int IValueTupleInternal.GetHashCode(IEqualityComparer comparer) @@ -1833,13 +1833,13 @@ namespace System private int GetHashCodeCore(IEqualityComparer comparer) { - return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1), - comparer.GetHashCode(Item2), - comparer.GetHashCode(Item3), - comparer.GetHashCode(Item4), - comparer.GetHashCode(Item5), - comparer.GetHashCode(Item6), - comparer.GetHashCode(Item7)); + return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1!), + comparer.GetHashCode(Item2!), + comparer.GetHashCode(Item3!), + comparer.GetHashCode(Item4!), + comparer.GetHashCode(Item5!), + comparer.GetHashCode(Item6!), + comparer.GetHashCode(Item7!)); // TODO-NULLABLE-GENERIC } int IValueTupleInternal.GetHashCode(IEqualityComparer comparer) @@ -2202,9 +2202,9 @@ namespace System IValueTupleInternal? rest = Rest as IValueTupleInternal; if (rest == null) { - return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1), comparer.GetHashCode(Item2), comparer.GetHashCode(Item3), - comparer.GetHashCode(Item4), comparer.GetHashCode(Item5), comparer.GetHashCode(Item6), - comparer.GetHashCode(Item7)); + return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1!), comparer.GetHashCode(Item2!), comparer.GetHashCode(Item3!), + comparer.GetHashCode(Item4!), comparer.GetHashCode(Item5!), comparer.GetHashCode(Item6!), + comparer.GetHashCode(Item7!)); // TODO-NULLABLE-GENERIC } int size = rest.Length; @@ -2215,27 +2215,27 @@ namespace System switch (k) { case 1: - return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item7), rest.GetHashCode(comparer)); + return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item7!), rest.GetHashCode(comparer)); // TODO-NULLABLE-GENERIC case 2: - return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item6), comparer.GetHashCode(Item7), rest.GetHashCode(comparer)); + return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item6!), comparer.GetHashCode(Item7!), rest.GetHashCode(comparer)); // TODO-NULLABLE-GENERIC case 3: - return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item5), comparer.GetHashCode(Item6), comparer.GetHashCode(Item7), - rest.GetHashCode(comparer)); + return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item5!), comparer.GetHashCode(Item6!), comparer.GetHashCode(Item7!), + rest.GetHashCode(comparer)); // TODO-NULLABLE-GENERIC case 4: - return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item4), comparer.GetHashCode(Item5), comparer.GetHashCode(Item6), - comparer.GetHashCode(Item7), rest.GetHashCode(comparer)); + return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item4!), comparer.GetHashCode(Item5!), comparer.GetHashCode(Item6!), + comparer.GetHashCode(Item7!), rest.GetHashCode(comparer)); // TODO-NULLABLE-GENERIC case 5: - return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item3), comparer.GetHashCode(Item4), comparer.GetHashCode(Item5), - comparer.GetHashCode(Item6), comparer.GetHashCode(Item7), rest.GetHashCode(comparer)); + return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item3!), comparer.GetHashCode(Item4!), comparer.GetHashCode(Item5!), + comparer.GetHashCode(Item6!), comparer.GetHashCode(Item7!), rest.GetHashCode(comparer)); // TODO-NULLABLE-GENERIC case 6: - return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item2), comparer.GetHashCode(Item3), comparer.GetHashCode(Item4), - comparer.GetHashCode(Item5), comparer.GetHashCode(Item6), comparer.GetHashCode(Item7), - rest.GetHashCode(comparer)); + return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item2!), comparer.GetHashCode(Item3!), comparer.GetHashCode(Item4!), + comparer.GetHashCode(Item5!), comparer.GetHashCode(Item6!), comparer.GetHashCode(Item7!), + rest.GetHashCode(comparer)); // TODO-NULLABLE-GENERIC case 7: case 8: - return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1), comparer.GetHashCode(Item2), comparer.GetHashCode(Item3), - comparer.GetHashCode(Item4), comparer.GetHashCode(Item5), comparer.GetHashCode(Item6), - comparer.GetHashCode(Item7), rest.GetHashCode(comparer)); + return ValueTuple.CombineHashCodes(comparer.GetHashCode(Item1!), comparer.GetHashCode(Item2!), comparer.GetHashCode(Item3!), + comparer.GetHashCode(Item4!), comparer.GetHashCode(Item5!), comparer.GetHashCode(Item6!), + comparer.GetHashCode(Item7!), rest.GetHashCode(comparer)); // TODO-NULLABLE-GENERIC } Debug.Fail("Missed all cases for computing ValueTuple hash code"); -- 2.7.4