From 0ac0071e457434c73bdd119911d1094f6ccee544 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Mon, 24 Jan 2022 09:43:25 -0500 Subject: [PATCH] Implement IEquatable on value types overriding Equals (and enable CA1066/1077) (#63690) --- eng/CodeAnalysis.src.globalconfig | 4 +- .../System.Private.CoreLib.csproj | 2 - .../Diagnostics/SymbolStore/SymAddressKind.cs | 49 ------------ .../System/Diagnostics/SymbolStore/Token.cs | 39 ---------- .../src/System/Reflection/MdImport.cs | 2 + .../src/System/RuntimeHandles.cs | 2 +- .../src/System/ModuleHandle.cs | 2 +- .../General/TypeUnifier.NativeFormat.cs | 2 + .../Runtime/TypeInfos/RuntimeNamedTypeInfo.cs | 2 + .../NativeFormat/Generator/ReaderGen.cs | 1 + .../NativeFormat/NativeFormatReaderGen.cs | 1 + .../NativeFormat/NativeMetadataReader.cs | 7 +- .../Common/TypeSystem/Common/LayoutInt.cs | 2 + .../Unix/System.Native/Interop.IPAddress.cs | 16 +++- .../src/ServiceLookup/ServiceCacheKey.cs | 13 +++- ...crosoft.Extensions.Logging.Abstractions.cs | 2 +- .../src/EventId.cs | 3 +- .../ImmutableDictionary_2.HashBucket.cs | 2 + .../ImmutableHashSet_1.HashBucket.cs | 2 + .../ref/System.Collections.Specialized.cs | 5 +- .../Collections/Specialized/BitVector32.cs | 11 ++- .../tests/BitVector32Tests.cs | 15 ++++ .../ref/System.ComponentModel.Composition.cs | 3 +- .../ReflectionModel/LazyMemberInfo.cs | 25 +++--- .../System.ComponentModel.TypeConverter.cs | 3 +- .../MemberRelationshipService.cs | 50 +++++------- .../ComponentModel/InterlockedBitVector32.cs | 6 +- .../ref/System.Data.Common.cs | 39 ++++++---- .../src/System/Data/DataKey.cs | 4 +- .../src/System/Data/SQLTypes/SQLBinary.cs | 25 +++--- .../src/System/Data/SQLTypes/SQLBoolean.cs | 28 +++---- .../src/System/Data/SQLTypes/SQLByte.cs | 28 +++---- .../src/System/Data/SQLTypes/SQLDateTime.cs | 28 +++---- .../src/System/Data/SQLTypes/SQLDecimal.cs | 25 +++--- .../src/System/Data/SQLTypes/SQLDouble.cs | 28 +++---- .../src/System/Data/SQLTypes/SQLGuid.cs | 28 +++---- .../src/System/Data/SQLTypes/SQLInt16.cs | 28 +++---- .../src/System/Data/SQLTypes/SQLInt32.cs | 28 +++---- .../src/System/Data/SQLTypes/SQLInt64.cs | 28 +++---- .../src/System/Data/SQLTypes/SQLMoney.cs | 29 +++---- .../src/System/Data/SQLTypes/SQLSingle.cs | 28 +++---- .../src/System/Data/SQLTypes/SQLString.cs | 25 +++--- .../src/System/Data/Selection.cs | 14 ++-- .../System/Data/SqlTypes/SqlBinaryTest.cs | 3 + .../System/Data/SqlTypes/SqlBooleanTest.cs | 4 + .../tests/System/Data/SqlTypes/SqlByteTest.cs | 3 + .../System/Data/SqlTypes/SqlDateTimeTest.cs | 2 + .../System/Data/SqlTypes/SqlDecimalTest.cs | 2 + .../System/Data/SqlTypes/SqlDoubleTest.cs | 3 + .../tests/System/Data/SqlTypes/SqlGuidTest.cs | 3 + .../System/Data/SqlTypes/SqlInt16Test.cs | 3 + .../System/Data/SqlTypes/SqlInt64Test.cs | 3 + .../System/Data/SqlTypes/SqlMoneyTest.cs | 2 + .../System/Data/SqlTypes/SqlSingleTest.cs | 3 + .../System/Data/SqlTypes/SqlStringTest.cs | 3 + ...stem.Diagnostics.PerformanceCounter.csproj | 3 +- ...agnostics.PerformanceCounter.netcoreapp.cs | 12 +++ ...stem.Diagnostics.PerformanceCounter.csproj | 1 + .../src/System/Diagnostics/CounterSample.cs | 2 +- .../ref/System.Diagnostics.StackTrace.cs | 2 +- .../Diagnostics/SymbolStore/SymbolToken.cs | 2 +- .../ref/System.Drawing.Common.netcoreapp.cs | 4 + .../src/System/Drawing/CharacterRange.cs | 30 +++---- .../src/System/Drawing/Printing/TriState.cs | 78 +++++++------------ .../tests/CharacterRangeTests.cs | 1 + .../src/System/IO/Packaging/PackUriHelper.cs | 2 + .../Expressions/Interpreter/LocalVariables.cs | 23 ++---- .../ref/System.Net.Sockets.cs | 3 +- .../System/Net/Sockets/IPPacketInformation.cs | 48 ++++-------- .../IPPacketInformationTest.cs | 7 ++ .../src/System/ArraySegment.cs | 10 ++- .../Diagnostics/Tracing/EventDescriptor.cs | 2 +- .../src/System/HashCode.cs | 2 + .../src/System/IntPtr.cs | 2 + .../src/System/Nullable.cs | 2 + .../CustomAttributeNamedArgument.cs | 17 ++-- .../CustomAttributeTypedArgument.cs | 11 ++- .../InteropServices/ArrayWithOffset.cs | 4 +- .../Runtime/InteropServices/GCHandle.cs | 9 ++- .../Runtime/Serialization/StreamingContext.cs | 2 + .../src/System/Threading/CancellationToken.cs | 2 +- .../System/Threading/LowLevelLifoSemaphore.cs | 9 ++- .../PortableThreadPool.ThreadCounts.cs | 5 +- .../PortableThreadPool.WorkerTracking.cs | 11 ++- .../src/System/TimeZoneInfo.AdjustmentRule.cs | 6 ++ .../src/System/UIntPtr.cs | 2 + .../System/Xml/BinaryXml/XmlBinaryReader.cs | 49 ++++-------- .../src/System/Xml/Xsl/Pair.cs | 43 ++++------ .../src/System/Xml/Xsl/XmlQueryCardinality.cs | 2 +- .../System/Runtime/Caching/CacheExpires.cs | 55 +++---------- .../src/System/Runtime/Caching/CacheUsage.cs | 62 +++------------ .../ref/System.Runtime.InteropServices.cs | 2 +- .../Runtime/InteropServices/GCHandleTests.cs | 1 + .../System.Runtime/ref/System.Runtime.cs | 18 +++-- ...stomAttribute_Named_Typed_ArgumentTests.cs | 22 ++++++ ...iceProcess.ServiceController.netcoreapp.cs | 3 + ...em.ServiceProcess.ServiceController.csproj | 2 + .../SessionChangeDescription.cs | 39 ++++------ .../src/Internal/Synthesis/EngineSiteSapi.cs | 38 ++++----- .../System.Text.Rune.netstandard20.cs | 2 +- .../Symbolic/SymbolicMatch.cs | 12 ++- .../Symbolic/SymbolicRegexInfo.cs | 6 +- .../System.Threading/ref/System.Threading.cs | 2 +- .../src/System/Threading/LockCookie.cs | 37 +++------ .../ref/System.Transactions.Local.cs | 5 +- .../System/Transactions/TransactionOptions.cs | 7 +- .../src/Mono/RuntimeHandles.cs | 6 +- .../src/System/ModuleHandle.cs | 2 +- .../src/System/Nullable.Mono.cs | 2 + .../BrowserDebugProxy/DevToolsHelper.cs | 12 ++- .../WasmAppBuilder/PInvokeTableGenerator.cs | 2 + 111 files changed, 650 insertions(+), 813 deletions(-) delete mode 100644 src/coreclr/System.Private.CoreLib/src/System/Diagnostics/SymbolStore/SymAddressKind.cs delete mode 100644 src/coreclr/System.Private.CoreLib/src/System/Diagnostics/SymbolStore/Token.cs create mode 100644 src/libraries/System.Diagnostics.PerformanceCounter/ref/System.Diagnostics.PerformanceCounter.netcoreapp.cs diff --git a/eng/CodeAnalysis.src.globalconfig b/eng/CodeAnalysis.src.globalconfig index 0fc9bf8e5a7ee..e5ae41903b5a7 100644 --- a/eng/CodeAnalysis.src.globalconfig +++ b/eng/CodeAnalysis.src.globalconfig @@ -152,10 +152,10 @@ dotnet_diagnostic.CA1064.severity = none dotnet_diagnostic.CA1065.severity = none # CA1066: Implement IEquatable when overriding Object.Equals -dotnet_diagnostic.CA1066.severity = none +dotnet_diagnostic.CA1066.severity = warning # CA1067: Override Object.Equals(object) when implementing IEquatable -dotnet_diagnostic.CA1067.severity = none +dotnet_diagnostic.CA1067.severity = warning # CA1068: CancellationToken parameters must come last dotnet_diagnostic.CA1068.severity = none diff --git a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj index e1230d59401d8..3d21bffd3d24f 100644 --- a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -140,8 +140,6 @@ - - diff --git a/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/SymbolStore/SymAddressKind.cs b/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/SymbolStore/SymAddressKind.cs deleted file mode 100644 index dc2a0a05708c1..0000000000000 --- a/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/SymbolStore/SymAddressKind.cs +++ /dev/null @@ -1,49 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*============================================================ -** -** -** -** Represents address Kinds used with local variables, parameters, and -** fields. -** -** -===========================================================*/ -// Only statics, does not need to be marked with the serializable attribute - -namespace System.Diagnostics.SymbolStore -{ - internal enum SymAddressKind - { - // ILOffset: addr1 = IL local var or param index. - ILOffset = 1, - - // NativeRVA: addr1 = RVA into module. - NativeRVA = 2, - - // NativeRegister: addr1 = register the var is stored in. - NativeRegister = 3, - - // NativeRegisterRelative: addr1 = register, addr2 = offset. - NativeRegisterRelative = 4, - - // NativeOffset: addr1 = offset from start of parent. - NativeOffset = 5, - - // NativeRegisterRegister: addr1 = reg low, addr2 = reg high. - NativeRegisterRegister = 6, - - // NativeRegisterStack: addr1 = reg low, addr2 = reg stk, addr3 = offset. - NativeRegisterStack = 7, - - // NativeStackRegister: addr1 = reg stk, addr2 = offset, addr3 = reg high. - NativeStackRegister = 8, - - // BitField: addr1 = field start, addr = field length. - BitField = 9, - - // NativeSectionOffset: addr1 = section, addr = offset - NativeSectionOffset = 10, - } -} diff --git a/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/SymbolStore/Token.cs b/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/SymbolStore/Token.cs deleted file mode 100644 index fbd9f7e4bc1ae..0000000000000 --- a/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/SymbolStore/Token.cs +++ /dev/null @@ -1,39 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*============================================================ -** -** -** Small value class used by the SymbolStore package for passing -** around metadata tokens. -** -===========================================================*/ - -using System.Diagnostics.CodeAnalysis; - -namespace System.Diagnostics.SymbolStore -{ - internal struct SymbolToken - { - internal int m_token; - - public SymbolToken(int val) { m_token = val; } - - public int GetToken() { return m_token; } - - public override int GetHashCode() { return m_token; } - - public override bool Equals([NotNullWhen(true)] object? obj) - { - if (obj is SymbolToken) - return Equals((SymbolToken)obj); - else - return false; - } - - public bool Equals(SymbolToken obj) - { - return obj.m_token == m_token; - } - } -} diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdImport.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdImport.cs index 9368fc25d340b..cdc15dc8fb6e0 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdImport.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdImport.cs @@ -194,7 +194,9 @@ internal unsafe struct MetadataEnumResult } } +#pragma warning disable CA1066 // IEquatable interface implementation isn't used internal readonly struct MetadataImport +#pragma warning restore CA1067 { private readonly IntPtr m_metadataImport2; private readonly object? m_keepalive; diff --git a/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs b/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs index 977d73e5c3b99..32a37b6d4219f 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs @@ -1246,7 +1246,7 @@ public void GetObjectData(SerializationInfo info, StreamingContext context) } } - public unsafe partial struct ModuleHandle + public unsafe partial struct ModuleHandle : IEquatable { #region Public Static Members public static readonly ModuleHandle EmptyHandle; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/ModuleHandle.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/ModuleHandle.cs index 3714e7ce510fb..d1bb831f34772 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/ModuleHandle.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/ModuleHandle.cs @@ -6,7 +6,7 @@ namespace System { - public struct ModuleHandle + public struct ModuleHandle : IEquatable { public static readonly ModuleHandle EmptyHandle; diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/TypeUnifier.NativeFormat.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/TypeUnifier.NativeFormat.cs index b44cf57cdff6d..fe06816cf93e3 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/TypeUnifier.NativeFormat.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/TypeUnifier.NativeFormat.cs @@ -34,6 +34,8 @@ // - The TypeUnifier extension class provides a more friendly interface to the rest of the codebase. // +#pragma warning disable CA1067 // override Equals because it implements IEquatable + namespace System.Reflection.Runtime.General { internal static partial class TypeUnifier diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeNamedTypeInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeNamedTypeInfo.cs index 209a91e0cb102..fdbcf0b53685d 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeNamedTypeInfo.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeNamedTypeInfo.cs @@ -10,6 +10,8 @@ using Internal.Reflection.Tracing; +#pragma warning disable CA1067 // override Equals because it implements IEquatable + namespace System.Reflection.Runtime.TypeInfos { // diff --git a/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/Generator/ReaderGen.cs b/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/Generator/ReaderGen.cs index 55b09b37b3431..aa1a796bfaa0f 100644 --- a/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/Generator/ReaderGen.cs +++ b/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/Generator/ReaderGen.cs @@ -20,6 +20,7 @@ public void EmitSource() WriteLine("#pragma warning disable 649"); WriteLine("#pragma warning disable 169"); WriteLine("#pragma warning disable 282 // There is no defined ordering between fields in multiple declarations of partial class or struct"); + WriteLine("#pragma warning disable CA1066 // IEquatable implementations aren't used"); WriteLine("#pragma warning disable IDE0059"); WriteLine(); diff --git a/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeFormatReaderGen.cs b/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeFormatReaderGen.cs index 1d92be5677148..bbc23ec878484 100644 --- a/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeFormatReaderGen.cs +++ b/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeFormatReaderGen.cs @@ -6,6 +6,7 @@ #pragma warning disable 649 #pragma warning disable 169 #pragma warning disable 282 // There is no defined ordering between fields in multiple declarations of partial class or struct +#pragma warning disable CA1066 // IEquatable implementations aren't used #pragma warning disable IDE0059 using System; diff --git a/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeMetadataReader.cs b/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeMetadataReader.cs index 8eba905400e42..5b7921f972f97 100644 --- a/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeMetadataReader.cs +++ b/src/coreclr/tools/Common/Internal/Metadata/NativeFormat/NativeMetadataReader.cs @@ -1,12 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. - #pragma warning disable 169 - -// There is no defined ordering between fields in multiple declarations of partial class or struct -#pragma warning disable 282 - +#pragma warning disable 282 // There is no defined ordering between fields in multiple declarations of partial class or struct +#pragma warning disable CA1066 // IEquatable implementations aren't used using System; using System.IO; diff --git a/src/coreclr/tools/Common/TypeSystem/Common/LayoutInt.cs b/src/coreclr/tools/Common/TypeSystem/Common/LayoutInt.cs index 2ec3883af9f08..c794377bf1971 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/LayoutInt.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/LayoutInt.cs @@ -12,7 +12,9 @@ namespace Internal.TypeSystem /// type system do not have a known size. This type is used to make such sizes viral through the type layout /// computations) /// +#pragma warning disable CA1066 // IEquatable implementation wouldn't be used public struct LayoutInt +#pragma warning restore CA1066 { private int _value; diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.IPAddress.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.IPAddress.cs index 567f97df901ce..4bbd79987510b 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.IPAddress.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.IPAddress.cs @@ -2,9 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; -using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; -using System.Text; internal static partial class Interop { @@ -33,6 +32,19 @@ public bool IsIPv6 private uint _isIPv6; // Non-zero if this is an IPv6 address; zero for IPv4. internal uint ScopeId; // Scope ID (IPv6 only) + public override unsafe int GetHashCode() + { + HashCode h = default; + fixed (byte* ptr = Address) + { + h.AddBytes(new ReadOnlySpan(ptr, IsIPv6 ? IPv6AddressBytes : IPv4AddressBytes)); + } + return h.ToHashCode(); + } + + public override bool Equals([NotNullWhen(true)] object? obj) => + obj is IPAddress other && Equals(other); + public bool Equals(IPAddress other) { int addressByteCount; diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceCacheKey.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceCacheKey.cs index 8f812ae45e6a8..737c23d7f4445 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceCacheKey.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceCacheKey.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics.CodeAnalysis; namespace Microsoft.Extensions.DependencyInjection.ServiceLookup { @@ -33,10 +34,14 @@ public ServiceCacheKey(Type? type, int slot) Slot = slot; } - public bool Equals(ServiceCacheKey other) - { - return Type == other.Type && Slot == other.Slot; - } + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(ServiceCacheKey other) => + Type == other.Type && Slot == other.Slot; + + public override bool Equals([NotNullWhen(true)] object? obj) => + obj is ServiceCacheKey other && Equals(other); public override int GetHashCode() { diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/ref/Microsoft.Extensions.Logging.Abstractions.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/ref/Microsoft.Extensions.Logging.Abstractions.cs index 1404880a97288..33e79ca09252e 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/ref/Microsoft.Extensions.Logging.Abstractions.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/ref/Microsoft.Extensions.Logging.Abstractions.cs @@ -6,7 +6,7 @@ namespace Microsoft.Extensions.Logging { - public readonly partial struct EventId + public readonly partial struct EventId : System.IEquatable { private readonly object _dummy; private readonly int _dummyPrimitive; diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/EventId.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/EventId.cs index 972fb1ec0488c..1cb4775b275b9 100644 --- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/EventId.cs +++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/src/EventId.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; using System.Diagnostics.CodeAnalysis; namespace Microsoft.Extensions.Logging @@ -8,7 +9,7 @@ namespace Microsoft.Extensions.Logging /// /// Identifies a logging event. The primary identifier is the "Id" property, with the "Name" property providing a short description of this type of event. /// - public readonly struct EventId + public readonly struct EventId : IEquatable { /// /// Implicitly creates an EventId from the given . diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableDictionary_2.HashBucket.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableDictionary_2.HashBucket.cs index aa8d7636cfbca..2562372c666b4 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableDictionary_2.HashBucket.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableDictionary_2.HashBucket.cs @@ -15,7 +15,9 @@ public partial class ImmutableDictionary /// /// Contains all the key/values in the collection that hash to the same value. /// +#pragma warning disable CA1066 // Implement IEquatable when overriding Object.Equals internal readonly struct HashBucket : IEnumerable> +#pragma warning restore CA1066 { /// /// One of the values in this bucket. diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableHashSet_1.HashBucket.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableHashSet_1.HashBucket.cs index 82fd48fbc62e5..04ca794da7808 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableHashSet_1.HashBucket.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableHashSet_1.HashBucket.cs @@ -30,7 +30,9 @@ internal enum OperationResult /// /// Contains all the keys in the collection that hash to the same value. /// +#pragma warning disable CA1066 // Implement IEquatable when overriding Object.Equals internal readonly struct HashBucket +#pragma warning restore CA1066 { /// /// One of the values in this bucket. diff --git a/src/libraries/System.Collections.Specialized/ref/System.Collections.Specialized.cs b/src/libraries/System.Collections.Specialized/ref/System.Collections.Specialized.cs index 1864717141ca4..00fc77efe910c 100644 --- a/src/libraries/System.Collections.Specialized/ref/System.Collections.Specialized.cs +++ b/src/libraries/System.Collections.Specialized/ref/System.Collections.Specialized.cs @@ -6,7 +6,7 @@ namespace System.Collections.Specialized { - public partial struct BitVector32 + public partial struct BitVector32 : System.IEquatable { private int _dummyPrimitive; public BitVector32(System.Collections.Specialized.BitVector32 value) { throw null; } @@ -18,11 +18,12 @@ public partial struct BitVector32 public static int CreateMask(int previous) { throw null; } public static System.Collections.Specialized.BitVector32.Section CreateSection(short maxValue) { throw null; } public static System.Collections.Specialized.BitVector32.Section CreateSection(short maxValue, System.Collections.Specialized.BitVector32.Section previous) { throw null; } + public bool Equals(System.Collections.Specialized.BitVector32 other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? o) { throw null; } public override int GetHashCode() { throw null; } public override string ToString() { throw null; } public static string ToString(System.Collections.Specialized.BitVector32 value) { throw null; } - public readonly partial struct Section + public readonly partial struct Section : System.IEquatable { private readonly int _dummyPrimitive; public short Mask { get { throw null; } } diff --git a/src/libraries/System.Collections.Specialized/src/System/Collections/Specialized/BitVector32.cs b/src/libraries/System.Collections.Specialized/src/System/Collections/Specialized/BitVector32.cs index ce4ba761ab7af..60a2580cfb6fd 100644 --- a/src/libraries/System.Collections.Specialized/src/System/Collections/Specialized/BitVector32.cs +++ b/src/libraries/System.Collections.Specialized/src/System/Collections/Specialized/BitVector32.cs @@ -10,7 +10,7 @@ namespace System.Collections.Specialized /// Provides a simple light bit vector with easy integer or Boolean access to /// a 32 bit storage. /// - public struct BitVector32 + public struct BitVector32 : IEquatable { private uint _data; @@ -151,7 +151,12 @@ private static Section CreateSectionHelper(short maxValue, short priorMask, shor return new Section(mask, offset); } - public override bool Equals([NotNullWhen(true)] object? o) => o is BitVector32 other && _data == other._data; + public override bool Equals([NotNullWhen(true)] object? o) => o is BitVector32 other && Equals(other); + + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(BitVector32 other) => _data == other._data; public override int GetHashCode() => _data.GetHashCode(); @@ -182,7 +187,7 @@ public override string ToString() /// /// Represents an section of the vector that can contain a integer number. /// - public readonly struct Section + public readonly struct Section : IEquatable
{ private readonly short _mask; private readonly short _offset; diff --git a/src/libraries/System.Collections.Specialized/tests/BitVector32Tests.cs b/src/libraries/System.Collections.Specialized/tests/BitVector32Tests.cs index 61734a09b741f..69453b6c574d5 100644 --- a/src/libraries/System.Collections.Specialized/tests/BitVector32Tests.cs +++ b/src/libraries/System.Collections.Specialized/tests/BitVector32Tests.cs @@ -518,17 +518,32 @@ public static void EqualsTest() Assert.True(new BitVector32(0).Equals(original)); Assert.True(original.Equals(new BitVector32(0))); + Assert.True(original.Equals((object)original)); + Assert.True(new BitVector32().Equals((object)original)); + Assert.True(original.Equals((object)new BitVector32())); + Assert.True(new BitVector32(0).Equals((object)original)); + Assert.True(original.Equals((object)new BitVector32(0))); + BitVector32 other = new BitVector32(int.MaxValue / 2 - 1); Assert.True(other.Equals(other)); Assert.True(new BitVector32(int.MaxValue / 2 - 1).Equals(other)); Assert.True(other.Equals(new BitVector32(int.MaxValue / 2 - 1))); + Assert.True(other.Equals((object)other)); + Assert.True(new BitVector32(int.MaxValue / 2 - 1).Equals((object)other)); + Assert.True(other.Equals((object)new BitVector32(int.MaxValue / 2 - 1))); + Assert.False(other.Equals(original)); Assert.False(original.Equals(other)); Assert.False(other.Equals(null)); Assert.False(original.Equals(null)); Assert.False(other.Equals(int.MaxValue / 2 - 1)); Assert.False(original.Equals(0)); + + Assert.False(other.Equals((object)original)); + Assert.False(original.Equals((object)other)); + Assert.False(other.Equals(int.MaxValue / 2 - 1)); + Assert.False(original.Equals(0)); } [Fact] diff --git a/src/libraries/System.ComponentModel.Composition/ref/System.ComponentModel.Composition.cs b/src/libraries/System.ComponentModel.Composition/ref/System.ComponentModel.Composition.cs index f55f6b216d37f..60accaee91e87 100644 --- a/src/libraries/System.ComponentModel.Composition/ref/System.ComponentModel.Composition.cs +++ b/src/libraries/System.ComponentModel.Composition/ref/System.ComponentModel.Composition.cs @@ -608,7 +608,7 @@ public partial class ImportDefinition } namespace System.ComponentModel.Composition.ReflectionModel { - public partial struct LazyMemberInfo + public partial struct LazyMemberInfo : System.IEquatable { private object _dummy; private int _dummyPrimitive; @@ -616,6 +616,7 @@ public partial struct LazyMemberInfo public LazyMemberInfo(System.Reflection.MemberTypes memberType, System.Func accessorsCreator) { throw null; } public LazyMemberInfo(System.Reflection.MemberTypes memberType, params System.Reflection.MemberInfo[] accessors) { throw null; } public System.Reflection.MemberTypes MemberType { get { throw null; } } + public bool Equals(System.ComponentModel.Composition.ReflectionModel.LazyMemberInfo other) { throw null; } public override bool Equals(object? obj) { throw null; } public System.Reflection.MemberInfo[] GetAccessors() { throw null; } public override int GetHashCode() { throw null; } diff --git a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/ReflectionModel/LazyMemberInfo.cs b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/ReflectionModel/LazyMemberInfo.cs index 480e339c4080f..02d1f811e71b7 100644 --- a/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/ReflectionModel/LazyMemberInfo.cs +++ b/src/libraries/System.ComponentModel.Composition/src/System/ComponentModel/Composition/ReflectionModel/LazyMemberInfo.cs @@ -8,7 +8,7 @@ namespace System.ComponentModel.Composition.ReflectionModel { - public struct LazyMemberInfo + public struct LazyMemberInfo : IEquatable { private readonly MemberTypes _memberType; private MemberInfo?[]? _accessors; @@ -106,31 +106,32 @@ public override int GetHashCode() throw new Exception(SR.Diagnostic_InternalExceptionMessage); } - public override bool Equals(object? obj) - { - if (obj is not LazyMemberInfo that) - { - return false; - } + public override bool Equals(object? obj) => + obj is LazyMemberInfo other && Equals(other); + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(LazyMemberInfo other) + { // Different member types mean different members - if (_memberType != that._memberType) + if (_memberType != other._memberType) { return false; } // if any of the lazy memebers create accessors in a delay-loaded fashion, we simply compare the creators - if ((_accessorsCreator != null) || (that._accessorsCreator != null)) + if ((_accessorsCreator != null) || (other._accessorsCreator != null)) { - return object.Equals(_accessorsCreator, that._accessorsCreator); + return object.Equals(_accessorsCreator, other._accessorsCreator); } // we are dealing with explicitly passed accessors in both cases - if (_accessors == null || that._accessors == null) + if (_accessors == null || other._accessors == null) { throw new Exception(SR.Diagnostic_InternalExceptionMessage); } - return _accessors.SequenceEqual(that._accessors); + return _accessors.SequenceEqual(other._accessors); } public static bool operator ==(LazyMemberInfo left, LazyMemberInfo right) diff --git a/src/libraries/System.ComponentModel.TypeConverter/ref/System.ComponentModel.TypeConverter.cs b/src/libraries/System.ComponentModel.TypeConverter/ref/System.ComponentModel.TypeConverter.cs index 510fffca71406..8fe3c9a37f821 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/ref/System.ComponentModel.TypeConverter.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/ref/System.ComponentModel.TypeConverter.cs @@ -2164,7 +2164,7 @@ public sealed partial class InstanceDescriptor public object? Invoke() { throw null; } } [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] - public readonly partial struct MemberRelationship + public readonly partial struct MemberRelationship : System.IEquatable { private readonly object _dummy; private readonly int _dummyPrimitive; @@ -2173,6 +2173,7 @@ public sealed partial class InstanceDescriptor public bool IsEmpty { get { throw null; } } public System.ComponentModel.MemberDescriptor Member { get { throw null; } } public object? Owner { get { throw null; } } + public bool Equals(System.ComponentModel.Design.Serialization.MemberRelationship other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } public override int GetHashCode() { throw null; } public static bool operator ==(System.ComponentModel.Design.Serialization.MemberRelationship left, System.ComponentModel.Design.Serialization.MemberRelationship right) { throw null; } diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/MemberRelationshipService.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/MemberRelationshipService.cs index 6691792d7fcfe..090fa91accbf7 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/MemberRelationshipService.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/Serialization/MemberRelationshipService.cs @@ -153,7 +153,7 @@ private static void ThrowRelationshipNotSupported(MemberRelationship source, Mem /// /// Used as storage in our relationship table /// - private struct RelationshipEntry + private struct RelationshipEntry : IEquatable { internal WeakReference _owner; internal MemberDescriptor _member; @@ -169,20 +169,19 @@ internal RelationshipEntry(MemberRelationship rel) public override bool Equals([NotNullWhen(true)] object? o) { Debug.Assert(o is RelationshipEntry, "This is only called indirectly from a dictionary only containing RelationshipEntry structs."); - return this == (RelationshipEntry)o; + return Equals((RelationshipEntry)o); } - public static bool operator ==(RelationshipEntry re1, RelationshipEntry re2) + public bool Equals(RelationshipEntry other) { - object? owner1 = (re1._owner.IsAlive ? re1._owner.Target : null); - object? owner2 = (re2._owner.IsAlive ? re2._owner.Target : null); - return owner1 == owner2 && re1._member.Equals(re2._member); + object? owner1 = (_owner.IsAlive ? _owner.Target : null); + object? owner2 = (other._owner.IsAlive ? other._owner.Target : null); + return owner1 == owner2 && _member.Equals(other._member); } - public static bool operator !=(RelationshipEntry re1, RelationshipEntry re2) - { - return !(re1 == re2); - } + public static bool operator ==(RelationshipEntry re1, RelationshipEntry re2) => re1.Equals(re2); + + public static bool operator !=(RelationshipEntry re1, RelationshipEntry re2) => !re1.Equals(re2); public override int GetHashCode() => _hashCode; } @@ -191,7 +190,7 @@ public override bool Equals([NotNullWhen(true)] object? o) /// /// This class represents a single relationship between an object and a member. /// - public readonly struct MemberRelationship + public readonly struct MemberRelationship : IEquatable { public static readonly MemberRelationship Empty; @@ -222,37 +221,26 @@ public MemberRelationship(object owner, MemberDescriptor member) /// /// Infrastructure support to make this a first class struct /// - public override bool Equals([NotNullWhen(true)] object? obj) - { - return obj is MemberRelationship rel && rel.Owner == Owner && rel.Member == Member; - } + public override bool Equals([NotNullWhen(true)] object? obj) => obj is MemberRelationship rel && Equals(rel); /// /// Infrastructure support to make this a first class struct /// - public override int GetHashCode() - { - if (Owner == null) - { - return base.GetHashCode(); - } + public bool Equals(MemberRelationship other) => other.Owner == Owner && other.Member == Member; - return Owner.GetHashCode() ^ Member.GetHashCode(); - } /// /// Infrastructure support to make this a first class struct /// - public static bool operator ==(MemberRelationship left, MemberRelationship right) - { - return left.Owner == right.Owner && left.Member == right.Member; - } + public override int GetHashCode() => Owner is null ? base.GetHashCode() : Owner.GetHashCode() ^ Member.GetHashCode(); /// /// Infrastructure support to make this a first class struct /// - public static bool operator !=(MemberRelationship left, MemberRelationship right) - { - return !(left == right); - } + public static bool operator ==(MemberRelationship left, MemberRelationship right) => left.Equals(right); + + /// + /// Infrastructure support to make this a first class struct + /// + public static bool operator !=(MemberRelationship left, MemberRelationship right) => !left.Equals(right); } } diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/InterlockedBitVector32.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/InterlockedBitVector32.cs index 2190f32299fbb..7aa25ce5bdf63 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/InterlockedBitVector32.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/InterlockedBitVector32.cs @@ -11,7 +11,7 @@ namespace System.ComponentModel /// Provides a subset of the surface area, using volatile /// operations for reads and interlocked operations for writes. ///
- internal struct InterlockedBitVector32 + internal struct InterlockedBitVector32 : IEquatable { private int _data; @@ -44,7 +44,9 @@ public static int CreateMask(int previous) return previous == 0 ? 1 : previous << 1; } - public override bool Equals([NotNullWhen(true)] object? o) => o is InterlockedBitVector32 vector && _data == vector._data; + public override bool Equals([NotNullWhen(true)] object? o) => o is InterlockedBitVector32 other && Equals(other); + + public bool Equals(InterlockedBitVector32 other) => _data == other._data; public override int GetHashCode() => base.GetHashCode(); } diff --git a/src/libraries/System.Data.Common/ref/System.Data.Common.cs b/src/libraries/System.Data.Common/ref/System.Data.Common.cs index 569f83d8ac777..5e664573d5ea6 100644 --- a/src/libraries/System.Data.Common/ref/System.Data.Common.cs +++ b/src/libraries/System.Data.Common/ref/System.Data.Common.cs @@ -2737,7 +2737,7 @@ public sealed partial class SqlAlreadyFilledException : System.Data.SqlTypes.Sql public SqlAlreadyFilledException(string? message, System.Exception? e) { } } [System.Xml.Serialization.XmlSchemaProviderAttribute("GetXsdType")] - public partial struct SqlBinary : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public partial struct SqlBinary : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable, System.IEquatable { private object _dummy; private int _dummyPrimitive; @@ -2752,6 +2752,7 @@ public partial struct SqlBinary : System.Data.SqlTypes.INullable, System.ICompar public int CompareTo(object? value) { throw null; } public static System.Data.SqlTypes.SqlBinary Concat(System.Data.SqlTypes.SqlBinary x, System.Data.SqlTypes.SqlBinary y) { throw null; } public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlBinary x, System.Data.SqlTypes.SqlBinary y) { throw null; } + public bool Equals(System.Data.SqlTypes.SqlBinary other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; } public override int GetHashCode() { throw null; } public static System.Xml.XmlQualifiedName GetXsdType(System.Xml.Schema.XmlSchemaSet schemaSet) { throw null; } @@ -2777,7 +2778,7 @@ public partial struct SqlBinary : System.Data.SqlTypes.INullable, System.ICompar public override string ToString() { throw null; } } [System.Xml.Serialization.XmlSchemaProviderAttribute("GetXsdType")] - public partial struct SqlBoolean : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public partial struct SqlBoolean : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable, System.IEquatable { private int _dummyPrimitive; public static readonly System.Data.SqlTypes.SqlBoolean False; @@ -2796,6 +2797,7 @@ public partial struct SqlBoolean : System.Data.SqlTypes.INullable, System.ICompa public int CompareTo(System.Data.SqlTypes.SqlBoolean value) { throw null; } public int CompareTo(object? value) { throw null; } public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlBoolean x, System.Data.SqlTypes.SqlBoolean y) { throw null; } + public bool Equals(System.Data.SqlTypes.SqlBoolean other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; } public override int GetHashCode() { throw null; } public static System.Xml.XmlQualifiedName GetXsdType(System.Xml.Schema.XmlSchemaSet schemaSet) { throw null; } @@ -2847,7 +2849,7 @@ public partial struct SqlBoolean : System.Data.SqlTypes.INullable, System.ICompa public static System.Data.SqlTypes.SqlBoolean Xor(System.Data.SqlTypes.SqlBoolean x, System.Data.SqlTypes.SqlBoolean y) { throw null; } } [System.Xml.Serialization.XmlSchemaProviderAttribute("GetXsdType")] - public partial struct SqlByte : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public partial struct SqlByte : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable, System.IEquatable { private int _dummyPrimitive; public static readonly System.Data.SqlTypes.SqlByte MaxValue; @@ -2864,6 +2866,7 @@ public partial struct SqlByte : System.Data.SqlTypes.INullable, System.IComparab public int CompareTo(object? value) { throw null; } public static System.Data.SqlTypes.SqlByte Divide(System.Data.SqlTypes.SqlByte x, System.Data.SqlTypes.SqlByte y) { throw null; } public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlByte x, System.Data.SqlTypes.SqlByte y) { throw null; } + public bool Equals(System.Data.SqlTypes.SqlByte other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; } public override int GetHashCode() { throw null; } public static System.Xml.XmlQualifiedName GetXsdType(System.Xml.Schema.XmlSchemaSet schemaSet) { throw null; } @@ -2987,7 +2990,7 @@ public enum SqlCompareOptions BinarySort = 32768, } [System.Xml.Serialization.XmlSchemaProviderAttribute("GetXsdType")] - public partial struct SqlDateTime : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public partial struct SqlDateTime : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable, System.IEquatable { private int _dummyPrimitive; public static readonly System.Data.SqlTypes.SqlDateTime MaxValue; @@ -3010,6 +3013,7 @@ public partial struct SqlDateTime : System.Data.SqlTypes.INullable, System.IComp public int CompareTo(System.Data.SqlTypes.SqlDateTime value) { throw null; } public int CompareTo(object? value) { throw null; } public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlDateTime x, System.Data.SqlTypes.SqlDateTime y) { throw null; } + public bool Equals(System.Data.SqlTypes.SqlDateTime other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; } public override int GetHashCode() { throw null; } public static System.Xml.XmlQualifiedName GetXsdType(System.Xml.Schema.XmlSchemaSet schemaSet) { throw null; } @@ -3038,7 +3042,7 @@ public partial struct SqlDateTime : System.Data.SqlTypes.INullable, System.IComp public override string ToString() { throw null; } } [System.Xml.Serialization.XmlSchemaProviderAttribute("GetXsdType")] - public partial struct SqlDecimal : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public partial struct SqlDecimal : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable, System.IEquatable { private int _dummyPrimitive; public static readonly byte MaxPrecision; @@ -3068,6 +3072,7 @@ public partial struct SqlDecimal : System.Data.SqlTypes.INullable, System.ICompa public static System.Data.SqlTypes.SqlDecimal ConvertToPrecScale(System.Data.SqlTypes.SqlDecimal n, int precision, int scale) { throw null; } public static System.Data.SqlTypes.SqlDecimal Divide(System.Data.SqlTypes.SqlDecimal x, System.Data.SqlTypes.SqlDecimal y) { throw null; } public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlDecimal x, System.Data.SqlTypes.SqlDecimal y) { throw null; } + public bool Equals(System.Data.SqlTypes.SqlDecimal other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; } public static System.Data.SqlTypes.SqlDecimal Floor(System.Data.SqlTypes.SqlDecimal n) { throw null; } public override int GetHashCode() { throw null; } @@ -3124,7 +3129,7 @@ public partial struct SqlDecimal : System.Data.SqlTypes.INullable, System.ICompa public static System.Data.SqlTypes.SqlDecimal Truncate(System.Data.SqlTypes.SqlDecimal n, int position) { throw null; } } [System.Xml.Serialization.XmlSchemaProviderAttribute("GetXsdType")] - public partial struct SqlDouble : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public partial struct SqlDouble : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable, System.IEquatable { private int _dummyPrimitive; public static readonly System.Data.SqlTypes.SqlDouble MaxValue; @@ -3139,6 +3144,7 @@ public partial struct SqlDouble : System.Data.SqlTypes.INullable, System.ICompar public int CompareTo(object? value) { throw null; } public static System.Data.SqlTypes.SqlDouble Divide(System.Data.SqlTypes.SqlDouble x, System.Data.SqlTypes.SqlDouble y) { throw null; } public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlDouble x, System.Data.SqlTypes.SqlDouble y) { throw null; } + public bool Equals(System.Data.SqlTypes.SqlDouble other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; } public override int GetHashCode() { throw null; } public static System.Xml.XmlQualifiedName GetXsdType(System.Xml.Schema.XmlSchemaSet schemaSet) { throw null; } @@ -3187,7 +3193,7 @@ public partial struct SqlDouble : System.Data.SqlTypes.INullable, System.ICompar public override string ToString() { throw null; } } [System.Xml.Serialization.XmlSchemaProviderAttribute("GetXsdType")] - public partial struct SqlGuid : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public partial struct SqlGuid : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable, System.IEquatable { private object _dummy; private int _dummyPrimitive; @@ -3201,6 +3207,7 @@ public partial struct SqlGuid : System.Data.SqlTypes.INullable, System.IComparab public int CompareTo(System.Data.SqlTypes.SqlGuid value) { throw null; } public int CompareTo(object? value) { throw null; } public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlGuid x, System.Data.SqlTypes.SqlGuid y) { throw null; } + public bool Equals(System.Data.SqlTypes.SqlGuid other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; } public override int GetHashCode() { throw null; } public static System.Xml.XmlQualifiedName GetXsdType(System.Xml.Schema.XmlSchemaSet schemaSet) { throw null; } @@ -3229,7 +3236,7 @@ public partial struct SqlGuid : System.Data.SqlTypes.INullable, System.IComparab public override string ToString() { throw null; } } [System.Xml.Serialization.XmlSchemaProviderAttribute("GetXsdType")] - public partial struct SqlInt16 : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public partial struct SqlInt16 : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable, System.IEquatable { private int _dummyPrimitive; public static readonly System.Data.SqlTypes.SqlInt16 MaxValue; @@ -3246,6 +3253,7 @@ public partial struct SqlInt16 : System.Data.SqlTypes.INullable, System.ICompara public int CompareTo(object? value) { throw null; } public static System.Data.SqlTypes.SqlInt16 Divide(System.Data.SqlTypes.SqlInt16 x, System.Data.SqlTypes.SqlInt16 y) { throw null; } public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlInt16 x, System.Data.SqlTypes.SqlInt16 y) { throw null; } + public bool Equals(System.Data.SqlTypes.SqlInt16 other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; } public override int GetHashCode() { throw null; } public static System.Xml.XmlQualifiedName GetXsdType(System.Xml.Schema.XmlSchemaSet schemaSet) { throw null; } @@ -3303,7 +3311,7 @@ public partial struct SqlInt16 : System.Data.SqlTypes.INullable, System.ICompara public static System.Data.SqlTypes.SqlInt16 Xor(System.Data.SqlTypes.SqlInt16 x, System.Data.SqlTypes.SqlInt16 y) { throw null; } } [System.Xml.Serialization.XmlSchemaProviderAttribute("GetXsdType")] - public partial struct SqlInt32 : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public partial struct SqlInt32 : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable, System.IEquatable { private int _dummyPrimitive; public static readonly System.Data.SqlTypes.SqlInt32 MaxValue; @@ -3320,6 +3328,7 @@ public partial struct SqlInt32 : System.Data.SqlTypes.INullable, System.ICompara public int CompareTo(object? value) { throw null; } public static System.Data.SqlTypes.SqlInt32 Divide(System.Data.SqlTypes.SqlInt32 x, System.Data.SqlTypes.SqlInt32 y) { throw null; } public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlInt32 x, System.Data.SqlTypes.SqlInt32 y) { throw null; } + public bool Equals(System.Data.SqlTypes.SqlInt32 other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; } public override int GetHashCode() { throw null; } public static System.Xml.XmlQualifiedName GetXsdType(System.Xml.Schema.XmlSchemaSet schemaSet) { throw null; } @@ -3377,7 +3386,7 @@ public partial struct SqlInt32 : System.Data.SqlTypes.INullable, System.ICompara public static System.Data.SqlTypes.SqlInt32 Xor(System.Data.SqlTypes.SqlInt32 x, System.Data.SqlTypes.SqlInt32 y) { throw null; } } [System.Xml.Serialization.XmlSchemaProviderAttribute("GetXsdType")] - public partial struct SqlInt64 : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public partial struct SqlInt64 : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable, System.IEquatable { private int _dummyPrimitive; public static readonly System.Data.SqlTypes.SqlInt64 MaxValue; @@ -3394,6 +3403,7 @@ public partial struct SqlInt64 : System.Data.SqlTypes.INullable, System.ICompara public int CompareTo(object? value) { throw null; } public static System.Data.SqlTypes.SqlInt64 Divide(System.Data.SqlTypes.SqlInt64 x, System.Data.SqlTypes.SqlInt64 y) { throw null; } public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlInt64 x, System.Data.SqlTypes.SqlInt64 y) { throw null; } + public bool Equals(System.Data.SqlTypes.SqlInt64 other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; } public override int GetHashCode() { throw null; } public static System.Xml.XmlQualifiedName GetXsdType(System.Xml.Schema.XmlSchemaSet schemaSet) { throw null; } @@ -3451,7 +3461,7 @@ public partial struct SqlInt64 : System.Data.SqlTypes.INullable, System.ICompara public static System.Data.SqlTypes.SqlInt64 Xor(System.Data.SqlTypes.SqlInt64 x, System.Data.SqlTypes.SqlInt64 y) { throw null; } } [System.Xml.Serialization.XmlSchemaProviderAttribute("GetXsdType")] - public partial struct SqlMoney : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public partial struct SqlMoney : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable, System.IEquatable { private int _dummyPrimitive; public static readonly System.Data.SqlTypes.SqlMoney MaxValue; @@ -3469,6 +3479,7 @@ public partial struct SqlMoney : System.Data.SqlTypes.INullable, System.ICompara public int CompareTo(object? value) { throw null; } public static System.Data.SqlTypes.SqlMoney Divide(System.Data.SqlTypes.SqlMoney x, System.Data.SqlTypes.SqlMoney y) { throw null; } public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlMoney x, System.Data.SqlTypes.SqlMoney y) { throw null; } + public bool Equals(System.Data.SqlTypes.SqlMoney other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; } public override int GetHashCode() { throw null; } public static System.Xml.XmlQualifiedName GetXsdType(System.Xml.Schema.XmlSchemaSet schemaSet) { throw null; } @@ -3535,7 +3546,7 @@ public sealed partial class SqlNullValueException : System.Data.SqlTypes.SqlType public SqlNullValueException(string? message, System.Exception? e) { } } [System.Xml.Serialization.XmlSchemaProviderAttribute("GetXsdType")] - public partial struct SqlSingle : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public partial struct SqlSingle : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable, System.IEquatable { private int _dummyPrimitive; public static readonly System.Data.SqlTypes.SqlSingle MaxValue; @@ -3551,6 +3562,7 @@ public partial struct SqlSingle : System.Data.SqlTypes.INullable, System.ICompar public int CompareTo(object? value) { throw null; } public static System.Data.SqlTypes.SqlSingle Divide(System.Data.SqlTypes.SqlSingle x, System.Data.SqlTypes.SqlSingle y) { throw null; } public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlSingle x, System.Data.SqlTypes.SqlSingle y) { throw null; } + public bool Equals(System.Data.SqlTypes.SqlSingle other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; } public override int GetHashCode() { throw null; } public static System.Xml.XmlQualifiedName GetXsdType(System.Xml.Schema.XmlSchemaSet schemaSet) { throw null; } @@ -3599,7 +3611,7 @@ public partial struct SqlSingle : System.Data.SqlTypes.INullable, System.ICompar public override string ToString() { throw null; } } [System.Xml.Serialization.XmlSchemaProviderAttribute("GetXsdType")] - public partial struct SqlString : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public partial struct SqlString : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable, System.IEquatable { private object _dummy; private int _dummyPrimitive; @@ -3630,6 +3642,7 @@ public partial struct SqlString : System.Data.SqlTypes.INullable, System.ICompar public int CompareTo(object? value) { throw null; } public static System.Data.SqlTypes.SqlString Concat(System.Data.SqlTypes.SqlString x, System.Data.SqlTypes.SqlString y) { throw null; } public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlString x, System.Data.SqlTypes.SqlString y) { throw null; } + public bool Equals(System.Data.SqlTypes.SqlString other) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; } public override int GetHashCode() { throw null; } public byte[]? GetNonUnicodeBytes() { throw null; } diff --git a/src/libraries/System.Data.Common/src/System/Data/DataKey.cs b/src/libraries/System.Data.Common/src/System/Data/DataKey.cs index 379035bb75d6b..7f1a15f75f51b 100644 --- a/src/libraries/System.Data.Common/src/System/Data/DataKey.cs +++ b/src/libraries/System.Data.Common/src/System/Data/DataKey.cs @@ -5,7 +5,7 @@ namespace System.Data { - internal readonly struct DataKey + internal readonly struct DataKey : IEquatable { private const int maxColumns = 32; @@ -154,7 +154,7 @@ public override bool Equals(object? value) return Equals((DataKey)value); } - internal bool Equals(DataKey value) + public bool Equals(DataKey value) { //check to see if this.columns && key2's columns are equal... DataColumn[] column1 = _columns; diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLBinary.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLBinary.cs index a757be446e73a..f6a45dbba5f2c 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLBinary.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLBinary.cs @@ -12,7 +12,7 @@ namespace System.Data.SqlTypes { [XmlSchemaProvider("GetXsdType")] - public struct SqlBinary : INullable, IComparable, IXmlSerializable + public struct SqlBinary : INullable, IComparable, IXmlSerializable, IEquatable { // NOTE: If any instance fields change, update SqlTypeWorkarounds type in System.Data.SqlClient. private byte[]? _value; @@ -362,20 +362,15 @@ public int CompareTo(SqlBinary value) } // Compares this instance with a specified object - public override bool Equals([NotNullWhen(true)] object? value) - { - if (!(value is SqlBinary)) - { - return false; - } - - SqlBinary i = (SqlBinary)value; - - if (i.IsNull || IsNull) - return (i.IsNull && IsNull); - else - return (this == i).Value; - } + public override bool Equals([NotNullWhen(true)] object? value) => + value is SqlBinary other && Equals(other); + + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(SqlBinary other) => + other.IsNull || IsNull ? other.IsNull && IsNull : + (this == other).Value; // Hash a byte array. // Trailing zeroes/spaces would affect the hash value, so caller needs to diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLBoolean.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLBoolean.cs index 1efff18021e52..d7b723f9f05f0 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLBoolean.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLBoolean.cs @@ -18,7 +18,7 @@ namespace System.Data.SqlTypes [StructLayout(LayoutKind.Sequential)] [XmlSchemaProvider("GetXsdType")] [System.Runtime.CompilerServices.TypeForwardedFrom("System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] - public struct SqlBoolean : INullable, IComparable, IXmlSerializable + public struct SqlBoolean : INullable, IComparable, IXmlSerializable, IEquatable { // m_value: 2 (true), 1 (false), 0 (unknown/Null) private byte m_value; // Do not rename (binary serialization) @@ -465,26 +465,18 @@ public int CompareTo(SqlBoolean value) } // Compares this instance with a specified object - public override bool Equals([NotNullWhen(true)] object? value) - { - if (!(value is SqlBoolean)) - { - return false; - } - - SqlBoolean i = (SqlBoolean)value; + public override bool Equals([NotNullWhen(true)] object? value) => + value is SqlBoolean other && Equals(other); - if (i.IsNull || IsNull) - return (i.IsNull && IsNull); - else - return (this == i).Value; - } + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(SqlBoolean other) => + other.IsNull || IsNull ? other.IsNull && IsNull : + (this == other).Value; // For hashing purpose - public override int GetHashCode() - { - return IsNull ? 0 : Value.GetHashCode(); - } + public override int GetHashCode() => IsNull ? 0 : Value.GetHashCode(); XmlSchema? IXmlSerializable.GetSchema() { return null; } diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLByte.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLByte.cs index f7c1cdde43226..3dc5548ffed7a 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLByte.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLByte.cs @@ -18,7 +18,7 @@ namespace System.Data.SqlTypes [StructLayout(LayoutKind.Sequential)] [XmlSchemaProvider("GetXsdType")] [System.Runtime.CompilerServices.TypeForwardedFrom("System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] - public struct SqlByte : INullable, IComparable, IXmlSerializable + public struct SqlByte : INullable, IComparable, IXmlSerializable, IEquatable { private bool m_fNotNull; // false if null. Do not rename (binary serialization) private byte m_value; // Do not rename (binary serialization) @@ -474,26 +474,18 @@ public int CompareTo(SqlByte value) } // Compares this instance with a specified object - public override bool Equals([NotNullWhen(true)] object? value) - { - if (!(value is SqlByte)) - { - return false; - } - - SqlByte i = (SqlByte)value; + public override bool Equals([NotNullWhen(true)] object? value) => + value is SqlByte other && Equals(other); - if (i.IsNull || IsNull) - return (i.IsNull && IsNull); - else - return (this == i).Value; - } + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(SqlByte other) => + other.IsNull || IsNull ? other.IsNull && IsNull : + (this == other).Value; // For hashing purpose - public override int GetHashCode() - { - return IsNull ? 0 : Value.GetHashCode(); - } + public override int GetHashCode() => IsNull ? 0 : Value.GetHashCode(); XmlSchema? IXmlSerializable.GetSchema() { return null; } diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDateTime.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDateTime.cs index 195ca26628ea4..1edd44bedf338 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDateTime.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDateTime.cs @@ -21,7 +21,7 @@ namespace System.Data.SqlTypes [StructLayout(LayoutKind.Sequential)] [XmlSchemaProvider("GetXsdType")] [System.Runtime.CompilerServices.TypeForwardedFrom("System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] - public struct SqlDateTime : INullable, IComparable, IXmlSerializable + public struct SqlDateTime : INullable, IComparable, IXmlSerializable, IEquatable { private bool m_fNotNull; // false if null. Do not rename (binary serialization) private int m_day; // Day from 1900/1/1, could be negative. Range: Jan 1 1753 - Dec 31 9999. Do not rename (binary serialization) @@ -621,26 +621,18 @@ public int CompareTo(SqlDateTime value) } // Compares this instance with a specified object - public override bool Equals([NotNullWhen(true)] object? value) - { - if (!(value is SqlDateTime)) - { - return false; - } - - SqlDateTime i = (SqlDateTime)value; + public override bool Equals([NotNullWhen(true)] object? value) => + value is SqlDateTime other && Equals(other); - if (i.IsNull || IsNull) - return (i.IsNull && IsNull); - else - return (this == i).Value; - } + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(SqlDateTime other) => + other.IsNull || IsNull ? other.IsNull && IsNull : + (this == other).Value; // For hashing purpose - public override int GetHashCode() - { - return IsNull ? 0 : Value.GetHashCode(); - } + public override int GetHashCode() => IsNull ? 0 : Value.GetHashCode(); XmlSchema? IXmlSerializable.GetSchema() { return null; } diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDecimal.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDecimal.cs index 784d50d2bb1cf..336639fbf0e5b 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDecimal.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDecimal.cs @@ -18,7 +18,7 @@ namespace System.Data.SqlTypes ///
[StructLayout(LayoutKind.Sequential)] [XmlSchemaProvider("GetXsdType")] - public struct SqlDecimal : INullable, IComparable, IXmlSerializable + public struct SqlDecimal : INullable, IComparable, IXmlSerializable, IEquatable { // data in CSsNumeric in SQL Server // BYTE m_cbLen; // # of DWORDs + 1 (1 is for sign) @@ -3278,20 +3278,15 @@ public int CompareTo(SqlDecimal value) } // Compares this instance with a specified object - public override bool Equals([NotNullWhen(true)] object? value) - { - if (!(value is SqlDecimal)) - { - return false; - } - - SqlDecimal i = (SqlDecimal)value; - - if (i.IsNull || IsNull) - return (i.IsNull && IsNull); - else - return (this == i).Value; - } + public override bool Equals([NotNullWhen(true)] object? value) => + value is SqlDecimal other && Equals(other); + + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(SqlDecimal other) => + other.IsNull || IsNull ? other.IsNull && IsNull : + (this == other).Value; // For hashing purpose public override int GetHashCode() diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDouble.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDouble.cs index 3f10f94312400..4cc9ac4e321e0 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDouble.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDouble.cs @@ -19,7 +19,7 @@ namespace System.Data.SqlTypes [StructLayout(LayoutKind.Sequential)] [XmlSchemaProvider("GetXsdType")] [System.Runtime.CompilerServices.TypeForwardedFrom("System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] - public struct SqlDouble : INullable, IComparable, IXmlSerializable + public struct SqlDouble : INullable, IComparable, IXmlSerializable, IEquatable { private bool m_fNotNull; // false if null. Do not rename (binary serialization) private double m_value; // Do not rename (binary serialization) @@ -390,26 +390,18 @@ public int CompareTo(SqlDouble value) } // Compares this instance with a specified object - public override bool Equals([NotNullWhen(true)] object? value) - { - if (!(value is SqlDouble)) - { - return false; - } - - SqlDouble i = (SqlDouble)value; + public override bool Equals([NotNullWhen(true)] object? value) => + value is SqlDouble other && Equals(other); - if (i.IsNull || IsNull) - return (i.IsNull && IsNull); - else - return (this == i).Value; - } + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(SqlDouble other) => + other.IsNull || IsNull ? other.IsNull && IsNull : + (this == other).Value; // For hashing purpose - public override int GetHashCode() - { - return IsNull ? 0 : Value.GetHashCode(); - } + public override int GetHashCode() => IsNull ? 0 : Value.GetHashCode(); XmlSchema? IXmlSerializable.GetSchema() { return null; } diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLGuid.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLGuid.cs index 8e3c58dff3dad..2742c25d53b53 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLGuid.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLGuid.cs @@ -16,7 +16,7 @@ namespace System.Data.SqlTypes [Serializable] [XmlSchemaProvider("GetXsdType")] [System.Runtime.CompilerServices.TypeForwardedFrom("System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] - public struct SqlGuid : INullable, IComparable, IXmlSerializable + public struct SqlGuid : INullable, IComparable, IXmlSerializable, IEquatable { private const int SizeOfGuid = 16; @@ -281,26 +281,18 @@ public int CompareTo(SqlGuid value) } // Compares this instance with a specified object - public override bool Equals([NotNullWhen(true)] object? value) - { - if (!(value is SqlGuid)) - { - return false; - } - - SqlGuid i = (SqlGuid)value; + public override bool Equals([NotNullWhen(true)] object? value) => + value is SqlGuid other && Equals(other); - if (i.IsNull || IsNull) - return (i.IsNull && IsNull); - else - return (this == i).Value; - } + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(SqlGuid other) => + other.IsNull || IsNull ? other.IsNull && IsNull : + (this == other).Value; // For hashing purpose - public override int GetHashCode() - { - return IsNull ? 0 : Value.GetHashCode(); - } + public override int GetHashCode() => IsNull ? 0 : Value.GetHashCode(); XmlSchema? IXmlSerializable.GetSchema() { return null; } diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLInt16.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLInt16.cs index 5833a00938561..d3879a06cf91b 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLInt16.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLInt16.cs @@ -17,7 +17,7 @@ namespace System.Data.SqlTypes [StructLayout(LayoutKind.Sequential)] [XmlSchemaProvider("GetXsdType")] [System.Runtime.CompilerServices.TypeForwardedFrom("System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] - public struct SqlInt16 : INullable, IComparable, IXmlSerializable + public struct SqlInt16 : INullable, IComparable, IXmlSerializable, IEquatable { private bool m_fNotNull; // false if null. Do not rename (binary serialization) private short m_value; // Do not rename (binary serialization) @@ -475,26 +475,18 @@ public int CompareTo(SqlInt16 value) } // Compares this instance with a specified object - public override bool Equals([NotNullWhen(true)] object? value) - { - if (!(value is SqlInt16)) - { - return false; - } - - SqlInt16 i = (SqlInt16)value; + public override bool Equals([NotNullWhen(true)] object? value) => + value is SqlInt16 other && Equals(other); - if (i.IsNull || IsNull) - return (i.IsNull && IsNull); - else - return (this == i).Value; - } + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(SqlInt16 other) => + other.IsNull || IsNull ? other.IsNull && IsNull : + (this == other).Value; // For hashing purpose - public override int GetHashCode() - { - return IsNull ? 0 : Value.GetHashCode(); - } + public override int GetHashCode() => IsNull ? 0 : Value.GetHashCode(); XmlSchema? IXmlSerializable.GetSchema() { return null; } diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLInt32.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLInt32.cs index 271d6509e71f5..8ce08e74e4403 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLInt32.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLInt32.cs @@ -17,7 +17,7 @@ namespace System.Data.SqlTypes [StructLayout(LayoutKind.Sequential)] [XmlSchemaProvider("GetXsdType")] [System.Runtime.CompilerServices.TypeForwardedFrom("System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] - public struct SqlInt32 : INullable, IComparable, IXmlSerializable + public struct SqlInt32 : INullable, IComparable, IXmlSerializable, IEquatable { private bool m_fNotNull; // false if null, the default ctor (plain 0) will make it Null. Do not rename (binary serialization) private int m_value; // Do not rename (binary serialization) @@ -490,26 +490,18 @@ public int CompareTo(SqlInt32 value) } // Compares this instance with a specified object - public override bool Equals([NotNullWhen(true)] object? value) - { - if (!(value is SqlInt32)) - { - return false; - } - - SqlInt32 i = (SqlInt32)value; + public override bool Equals([NotNullWhen(true)] object? value) => + value is SqlInt32 other && Equals(other); - if (i.IsNull || IsNull) - return (i.IsNull && IsNull); - else - return (this == i).Value; - } + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(SqlInt32 other) => + other.IsNull || IsNull ? other.IsNull && IsNull : + (this == other).Value; // For hashing purpose - public override int GetHashCode() - { - return IsNull ? 0 : Value.GetHashCode(); - } + public override int GetHashCode() => IsNull ? 0 : Value.GetHashCode(); XmlSchema? IXmlSerializable.GetSchema() { return null; } diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLInt64.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLInt64.cs index b7f33674ce03a..393945b030395 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLInt64.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLInt64.cs @@ -18,7 +18,7 @@ namespace System.Data.SqlTypes [StructLayout(LayoutKind.Sequential)] [XmlSchemaProvider("GetXsdType")] [System.Runtime.CompilerServices.TypeForwardedFrom("System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] - public struct SqlInt64 : INullable, IComparable, IXmlSerializable + public struct SqlInt64 : INullable, IComparable, IXmlSerializable, IEquatable { private bool m_fNotNull; // false if null. Do not rename (binary serialization) private long m_value; // Do not rename (binary serialization) @@ -549,26 +549,18 @@ public int CompareTo(SqlInt64 value) } // Compares this instance with a specified object - public override bool Equals([NotNullWhen(true)] object? value) - { - if (!(value is SqlInt64)) - { - return false; - } - - SqlInt64 i = (SqlInt64)value; + public override bool Equals([NotNullWhen(true)] object? value) => + value is SqlInt64 other && Equals(other); - if (i.IsNull || IsNull) - return (i.IsNull && IsNull); - else - return (this == i).Value; - } + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(SqlInt64 other) => + other.IsNull || IsNull ? other.IsNull && IsNull : + (this == other).Value; // For hashing purpose - public override int GetHashCode() - { - return IsNull ? 0 : Value.GetHashCode(); - } + public override int GetHashCode() => IsNull ? 0 : Value.GetHashCode(); XmlSchema? IXmlSerializable.GetSchema() { return null; } diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLMoney.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLMoney.cs index 5431c8737d4af..64c0d168631c8 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLMoney.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLMoney.cs @@ -21,7 +21,7 @@ namespace System.Data.SqlTypes ///
[StructLayout(LayoutKind.Sequential)] [XmlSchemaProvider("GetXsdType")] - public struct SqlMoney : INullable, IComparable, IXmlSerializable + public struct SqlMoney : INullable, IComparable, IXmlSerializable, IEquatable { // NOTE: If any instance fields change, update SqlTypeWorkarounds type in System.Data.SqlClient. private bool _fNotNull; // false if null @@ -539,27 +539,20 @@ public int CompareTo(SqlMoney value) } // Compares this instance with a specified object - public override bool Equals([NotNullWhen(true)] object? value) - { - if (!(value is SqlMoney)) - { - return false; - } - - SqlMoney i = (SqlMoney)value; + public override bool Equals([NotNullWhen(true)] object? value) => + value is SqlMoney other && Equals(other); - if (i.IsNull || IsNull) - return (i.IsNull && IsNull); - else - return (this == i).Value; - } + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(SqlMoney other) => + other.IsNull || IsNull ? other.IsNull && IsNull : + (this == other).Value; // For hashing purpose - public override int GetHashCode() - { + public override int GetHashCode() => // Don't use Value property, because Value will convert to Decimal, which is not necessary. - return IsNull ? 0 : _value.GetHashCode(); - } + IsNull ? 0 : _value.GetHashCode(); XmlSchema? IXmlSerializable.GetSchema() { return null; } diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLSingle.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLSingle.cs index 59f29dcc89cbc..5fa7562824e13 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLSingle.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLSingle.cs @@ -17,7 +17,7 @@ namespace System.Data.SqlTypes /// [StructLayout(LayoutKind.Sequential)] [XmlSchemaProvider("GetXsdType")] - public struct SqlSingle : INullable, IComparable, IXmlSerializable + public struct SqlSingle : INullable, IComparable, IXmlSerializable, IEquatable { private bool _fNotNull; // false if null private float _value; @@ -400,26 +400,18 @@ public int CompareTo(SqlSingle value) } // Compares this instance with a specified object - public override bool Equals([NotNullWhen(true)] object? value) - { - if (!(value is SqlSingle)) - { - return false; - } - - SqlSingle i = (SqlSingle)value; + public override bool Equals([NotNullWhen(true)] object? value) => + value is SqlSingle other && Equals(other); - if (i.IsNull || IsNull) - return (i.IsNull && IsNull); - else - return (this == i).Value; - } + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(SqlSingle other) => + other.IsNull || IsNull ? other.IsNull && IsNull : + (this == other).Value; // For hashing purpose - public override int GetHashCode() - { - return IsNull ? 0 : Value.GetHashCode(); - } + public override int GetHashCode() => IsNull ? 0 : Value.GetHashCode(); XmlSchema? IXmlSerializable.GetSchema() { return null; } diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLString.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLString.cs index cac4122feba68..0c22570d2462d 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLString.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLString.cs @@ -34,7 +34,7 @@ public enum SqlCompareOptions [StructLayout(LayoutKind.Sequential)] [XmlSchemaProvider("GetXsdType")] [System.Runtime.CompilerServices.TypeForwardedFrom("System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] - public struct SqlString : INullable, IComparable, IXmlSerializable + public struct SqlString : INullable, IComparable, IXmlSerializable, IEquatable { private string? m_value; // Do not rename (binary serialization) private CompareInfo? m_cmpInfo; // Do not rename (binary serialization) @@ -871,20 +871,15 @@ public int CompareTo(SqlString value) } // Compares this instance with a specified object - public override bool Equals([NotNullWhen(true)] object? value) - { - if (!(value is SqlString)) - { - return false; - } - - SqlString i = (SqlString)value; - - if (i.IsNull || IsNull) - return (i.IsNull && IsNull); - else - return (this == i).Value; - } + public override bool Equals([NotNullWhen(true)] object? value) => + value is SqlString other && Equals(other); + + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(SqlString other) => + other.IsNull || IsNull ? other.IsNull && IsNull : + (this == other).Value; // For hashing purpose public override int GetHashCode() diff --git a/src/libraries/System.Data.Common/src/System/Data/Selection.cs b/src/libraries/System.Data.Common/src/System/Data/Selection.cs index 21a6d951393c1..fd76acfda7c36 100644 --- a/src/libraries/System.Data.Common/src/System/Data/Selection.cs +++ b/src/libraries/System.Data.Common/src/System/Data/Selection.cs @@ -9,7 +9,7 @@ namespace System.Data { - internal readonly struct IndexField + internal readonly struct IndexField : IEquatable { public readonly DataColumn Column; public readonly bool IsDescending; // false = Asc; true = Desc what is default value for this? @@ -22,15 +22,15 @@ internal IndexField(DataColumn column, bool isDescending) IsDescending = isDescending; } - public static bool operator ==(IndexField if1, IndexField if2) => - if1.Column == if2.Column && if1.IsDescending == if2.IsDescending; + public static bool operator ==(IndexField if1, IndexField if2) => if1.Equals(if2); - public static bool operator !=(IndexField if1, IndexField if2) => !(if1 == if2); + public static bool operator !=(IndexField if1, IndexField if2) => !if1.Equals(if2); // must override Equals if == operator is defined - public override bool Equals([NotNullWhen(true)] object? obj) => obj is IndexField ? - this == (IndexField)obj : - false; + public override bool Equals([NotNullWhen(true)] object? obj) => + obj is IndexField other && Equals(other); + + public bool Equals(IndexField other) => Column == other.Column && IsDescending == other.IsDescending; // must override GetHashCode if Equals is redefined public override int GetHashCode() => diff --git a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlBinaryTest.cs b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlBinaryTest.cs index 6a631b392bea9..8655d3feea003 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlBinaryTest.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlBinaryTest.cs @@ -122,8 +122,11 @@ public void ComparisonMethods() // Equals Assert.False(_test1.Equals(_test2)); + Assert.False(_test1.Equals((object)_test2)); Assert.False(_test3.Equals(_test2)); + Assert.False(_test3.Equals((object)_test2)); Assert.True(_test3.Equals(_test1)); + Assert.True(_test3.Equals((object)_test1)); // NotEquals Assert.True(SqlBinary.NotEquals(_test1, _test2).Value); diff --git a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlBooleanTest.cs b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlBooleanTest.cs index 4da63a4bcdcf8..b52f671dad2d4 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlBooleanTest.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlBooleanTest.cs @@ -242,10 +242,14 @@ public void EqualsTest() SqlBoolean sqlFalse2 = new SqlBoolean(false); Assert.True(_sqlTrue.Equals(sqlTrue2)); + Assert.True(_sqlTrue.Equals((object)sqlTrue2)); Assert.True(_sqlFalse.Equals(sqlFalse2)); + Assert.True(_sqlFalse.Equals((object)sqlFalse2)); Assert.False(_sqlTrue.Equals(_sqlFalse)); + Assert.False(_sqlTrue.Equals((object)_sqlFalse)); Assert.False(_sqlFalse.Equals(_sqlTrue)); + Assert.False(_sqlFalse.Equals((object)_sqlTrue)); Assert.False(_sqlTrue.Equals(SqlBoolean.Null)); Assert.False(_sqlFalse.Equals(SqlBoolean.Null)); diff --git a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlByteTest.cs b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlByteTest.cs index 2ae5976e9f1a9..9af75f4f46997 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlByteTest.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlByteTest.cs @@ -155,9 +155,12 @@ public void EqualsMethod() SqlByte testByte180II = new SqlByte(180); Assert.False(testByte0.Equals(testByte158)); + Assert.False(testByte0.Equals((object)testByte158)); Assert.False(testByte158.Equals(testByte180)); + Assert.False(testByte158.Equals((object)testByte180)); Assert.False(testByte180.Equals(new SqlString("TEST"))); Assert.True(testByte180.Equals(testByte180II)); + Assert.True(testByte180.Equals((object)testByte180II)); } [Fact] diff --git a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlDateTimeTest.cs b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlDateTimeTest.cs index 6d3287ed49b0f..0c835ff00c540 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlDateTimeTest.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlDateTimeTest.cs @@ -175,8 +175,10 @@ public void CompareTo() public void EqualsMethods() { Assert.False(_test1.Equals(_test2)); + Assert.False(_test1.Equals((object)_test2)); Assert.False(_test2.Equals(new SqlString("TEST"))); Assert.True(_test2.Equals(_test3)); + Assert.True(_test2.Equals((object)_test3)); // Static Equals()-method Assert.True(SqlDateTime.Equals(_test2, _test3).Value); diff --git a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlDecimalTest.cs b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlDecimalTest.cs index 6fd72ba4157aa..b9807ebcc102e 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlDecimalTest.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlDecimalTest.cs @@ -225,8 +225,10 @@ public void CompareTo() public void EqualsMethods() { Assert.False(_test1.Equals(_test2)); + Assert.False(_test1.Equals((object)_test2)); Assert.False(_test2.Equals(new SqlString("TEST"))); Assert.True(_test2.Equals(_test3)); + Assert.True(_test2.Equals((object)_test3)); // Static Equals()-method Assert.True(SqlDecimal.Equals(_test2, _test2).Value); diff --git a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlDoubleTest.cs b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlDoubleTest.cs index 4f0856e2ba226..db913271dc020 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlDoubleTest.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlDoubleTest.cs @@ -134,9 +134,12 @@ public void EqualsMethods() SqlDouble test22 = new SqlDouble(1.8e180); Assert.False(test0.Equals(test1)); + Assert.False(test0.Equals((object)test1)); Assert.False(test1.Equals(test2)); + Assert.False(test1.Equals((object)test2)); Assert.False(test2.Equals(new SqlString("TEST"))); Assert.True(test2.Equals(test22)); + Assert.True(test2.Equals((object)test22)); // Static Equals()-method Assert.True(SqlDouble.Equals(test2, test22).Value); diff --git a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlGuidTest.cs b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlGuidTest.cs index 84dcb3a3f5373..4c21e38d07ef2 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlGuidTest.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlGuidTest.cs @@ -126,9 +126,12 @@ public void CompareTo() public void EqualsMethods() { Assert.False(_test1.Equals(_test2)); + Assert.False(_test1.Equals((object)_test2)); Assert.False(_test2.Equals(_test4)); + Assert.False(_test2.Equals((object)_test4)); Assert.False(_test2.Equals(new SqlString("TEST"))); Assert.True(_test2.Equals(_test3)); + Assert.True(_test2.Equals((object)_test3)); // Static Equals()-method Assert.True(SqlGuid.Equals(_test2, _test3).Value); diff --git a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlInt16Test.cs b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlInt16Test.cs index 3c240d6d9ed0f..7c00f4845884d 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlInt16Test.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlInt16Test.cs @@ -157,9 +157,12 @@ public void EqualsMethod() SqlInt16 test180II = new SqlInt16(180); Assert.False(test0.Equals(test158)); + Assert.False(test0.Equals((object)test158)); Assert.False(test158.Equals(test180)); + Assert.False(test158.Equals((object)test180)); Assert.False(test180.Equals(new SqlString("TEST"))); Assert.True(test180.Equals(test180II)); + Assert.True(test180.Equals((object)test180II)); } [Fact] diff --git a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlInt64Test.cs b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlInt64Test.cs index 601b6a8bdb1bc..ed466fb50b277 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlInt64Test.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlInt64Test.cs @@ -159,9 +159,12 @@ public void EqualsMethod() SqlInt64 test180II = new SqlInt64(180); Assert.False(test0.Equals(test158)); + Assert.False(test0.Equals((object)test158)); Assert.False(test158.Equals(test180)); + Assert.False(test158.Equals((object)test180)); Assert.False(test180.Equals(new SqlString("TEST"))); Assert.True(test180.Equals(test180II)); + Assert.True(test180.Equals((object)test180II)); } [Fact] diff --git a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlMoneyTest.cs b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlMoneyTest.cs index 726302190b388..db99ba4de6691 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlMoneyTest.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlMoneyTest.cs @@ -131,7 +131,9 @@ public void CompareTo() public void EqualsMethods() { Assert.False(_test1.Equals(_test2)); + Assert.False(_test1.Equals((object)_test2)); Assert.True(_test2.Equals(_test3)); + Assert.True(_test2.Equals((object)_test3)); Assert.False(SqlMoney.Equals(_test1, _test2).Value); Assert.True(SqlMoney.Equals(_test3, _test2).Value); } diff --git a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlSingleTest.cs b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlSingleTest.cs index 2c92e08226e49..3ff6c803aaef6 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlSingleTest.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlSingleTest.cs @@ -132,9 +132,12 @@ public void EqualsMethods() SqlSingle test22 = new SqlSingle(1.8e32); Assert.False(test0.Equals(test1)); + Assert.False(test0.Equals((object)test1)); Assert.False(test1.Equals(test2)); + Assert.False(test1.Equals((object)test2)); Assert.False(test2.Equals(new SqlString("TEST"))); Assert.True(test2.Equals(test22)); + Assert.True(test2.Equals((object)test22)); // Static Equals()-method Assert.True(SqlSingle.Equals(test2, test22).Value); diff --git a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlStringTest.cs b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlStringTest.cs index 86a4b1683c4c9..56f8fa51b06ca 100644 --- a/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlStringTest.cs +++ b/src/libraries/System.Data.Common/tests/System/Data/SqlTypes/SqlStringTest.cs @@ -262,9 +262,12 @@ public void CompareTo() public void EqualsMethods() { Assert.False(_test1.Equals(_test2)); + Assert.False(_test1.Equals((object)_test2)); Assert.False(_test3.Equals(_test1)); + Assert.False(_test3.Equals((object)_test1)); Assert.False(_test2.Equals(new SqlString("TEST"))); Assert.True(_test2.Equals(_test3)); + Assert.True(_test2.Equals((object)_test3)); // Static Equals()-method Assert.True(SqlString.Equals(_test2, _test3).Value); diff --git a/src/libraries/System.Diagnostics.PerformanceCounter/ref/System.Diagnostics.PerformanceCounter.csproj b/src/libraries/System.Diagnostics.PerformanceCounter/ref/System.Diagnostics.PerformanceCounter.csproj index 9851685566186..220c3e850b5f1 100644 --- a/src/libraries/System.Diagnostics.PerformanceCounter/ref/System.Diagnostics.PerformanceCounter.csproj +++ b/src/libraries/System.Diagnostics.PerformanceCounter/ref/System.Diagnostics.PerformanceCounter.csproj @@ -6,6 +6,7 @@ + @@ -18,4 +19,4 @@ - \ No newline at end of file + diff --git a/src/libraries/System.Diagnostics.PerformanceCounter/ref/System.Diagnostics.PerformanceCounter.netcoreapp.cs b/src/libraries/System.Diagnostics.PerformanceCounter/ref/System.Diagnostics.PerformanceCounter.netcoreapp.cs new file mode 100644 index 0000000000000..b33f32066185b --- /dev/null +++ b/src/libraries/System.Diagnostics.PerformanceCounter/ref/System.Diagnostics.PerformanceCounter.netcoreapp.cs @@ -0,0 +1,12 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// ------------------------------------------------------------------------------ +// Changes to this file must follow the https://aka.ms/api-review process. +// ------------------------------------------------------------------------------ + +namespace System.Diagnostics +{ + public readonly partial struct CounterSample : System.IEquatable + { + } +} diff --git a/src/libraries/System.Diagnostics.PerformanceCounter/src/System.Diagnostics.PerformanceCounter.csproj b/src/libraries/System.Diagnostics.PerformanceCounter/src/System.Diagnostics.PerformanceCounter.csproj index 28133feec83ed..5ebf58e40c57e 100644 --- a/src/libraries/System.Diagnostics.PerformanceCounter/src/System.Diagnostics.PerformanceCounter.csproj +++ b/src/libraries/System.Diagnostics.PerformanceCounter/src/System.Diagnostics.PerformanceCounter.csproj @@ -3,6 +3,7 @@ true $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent);$(NetCoreAppMinimum)-windows;$(NetCoreAppMinimum);netstandard2.0;$(NetFrameworkMinimum) $(NoWarn);CA1847 + $(NoWarn);CA1066 annotations true Provides the System.Diagnostics.PerformanceCounter class, which allows access to Windows performance counters. diff --git a/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/CounterSample.cs b/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/CounterSample.cs index c89df23ed9aac..315ec5a87ccb4 100644 --- a/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/CounterSample.cs +++ b/src/libraries/System.Diagnostics.PerformanceCounter/src/System/Diagnostics/CounterSample.cs @@ -6,7 +6,7 @@ namespace System.Diagnostics /// /// A struct holding the raw data for a performance counter. /// - public readonly struct CounterSample + public readonly struct CounterSample : IEquatable { private readonly long _rawValue; private readonly long _baseValue; diff --git a/src/libraries/System.Diagnostics.StackTrace/ref/System.Diagnostics.StackTrace.cs b/src/libraries/System.Diagnostics.StackTrace/ref/System.Diagnostics.StackTrace.cs index 0efbf90bb1da1..60e755ecf790c 100644 --- a/src/libraries/System.Diagnostics.StackTrace/ref/System.Diagnostics.StackTrace.cs +++ b/src/libraries/System.Diagnostics.StackTrace/ref/System.Diagnostics.StackTrace.cs @@ -170,7 +170,7 @@ public enum SymAddressKind BitField = 9, NativeSectionOffset = 10, } - public readonly partial struct SymbolToken + public readonly partial struct SymbolToken : System.IEquatable { private readonly int _dummyPrimitive; public SymbolToken(int val) { throw null; } diff --git a/src/libraries/System.Diagnostics.StackTrace/src/System/Diagnostics/SymbolStore/SymbolToken.cs b/src/libraries/System.Diagnostics.StackTrace/src/System/Diagnostics/SymbolStore/SymbolToken.cs index b6a894f144fc9..8b27f618770fb 100644 --- a/src/libraries/System.Diagnostics.StackTrace/src/System/Diagnostics/SymbolStore/SymbolToken.cs +++ b/src/libraries/System.Diagnostics.StackTrace/src/System/Diagnostics/SymbolStore/SymbolToken.cs @@ -5,7 +5,7 @@ namespace System.Diagnostics.SymbolStore { - public readonly struct SymbolToken + public readonly struct SymbolToken : IEquatable { private readonly int _token; diff --git a/src/libraries/System.Drawing.Common/ref/System.Drawing.Common.netcoreapp.cs b/src/libraries/System.Drawing.Common/ref/System.Drawing.Common.netcoreapp.cs index f9d987de24d1c..1514ee19e8c33 100644 --- a/src/libraries/System.Drawing.Common/ref/System.Drawing.Common.netcoreapp.cs +++ b/src/libraries/System.Drawing.Common/ref/System.Drawing.Common.netcoreapp.cs @@ -6,6 +6,10 @@ namespace System.Drawing { + public partial struct CharacterRange : System.IEquatable + { + public bool Equals(System.Drawing.CharacterRange other) { throw null; } + } public sealed partial class Graphics { public void DrawRectangle(System.Drawing.Pen pen, System.Drawing.RectangleF rect) { } diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/CharacterRange.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/CharacterRange.cs index 157533b84283c..a0dccdc4b2876 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/CharacterRange.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/CharacterRange.cs @@ -7,51 +7,43 @@ namespace System.Drawing { [StructLayout(LayoutKind.Sequential)] - public struct CharacterRange + public struct CharacterRange : IEquatable { private int _first; private int _length; - /// - /// Initializes a new instance of the class with the specified coordinates. - /// + /// Initializes a new instance of the class with the specified coordinates. public CharacterRange(int First, int Length) { _first = First; _length = Length; } - /// - /// Gets the First character position of this . - /// + /// Gets the First character position of this . public int First { get => _first; set => _first = value; } - /// - /// Gets the Length of this . - /// + /// Gets the Length of this . public int Length { get => _length; set => _length = value; } - public override bool Equals([NotNullWhen(true)] object? obj) - { - if (!(obj is CharacterRange cr)) - { - return false; - } + public override bool Equals([NotNullWhen(true)] object? obj) => + obj is CharacterRange other && Equals(other); - return First == cr.First && Length == cr.Length; - } + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(CharacterRange other) => First == other.First && Length == other.Length; public static bool operator ==(CharacterRange cr1, CharacterRange cr2) => cr1.Equals(cr2); - public static bool operator !=(CharacterRange cr1, CharacterRange cr2) => !(cr1 == cr2); + public static bool operator !=(CharacterRange cr1, CharacterRange cr2) => !cr1.Equals(cr2); public override int GetHashCode() => HashCode.Combine(First, Length); } diff --git a/src/libraries/System.Drawing.Common/src/System/Drawing/Printing/TriState.cs b/src/libraries/System.Drawing.Common/src/System/Drawing/Printing/TriState.cs index 665a642a3e4f3..bb7b163d1ce95 100644 --- a/src/libraries/System.Drawing.Common/src/System/Drawing/Printing/TriState.cs +++ b/src/libraries/System.Drawing.Common/src/System/Drawing/Printing/TriState.cs @@ -1,9 +1,12 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; + namespace System.Drawing.Printing { - internal readonly partial struct TriState + internal readonly partial struct TriState : IEquatable { private readonly byte _value; // 0 is "default", not false @@ -11,73 +14,46 @@ namespace System.Drawing.Printing public static readonly TriState False = new TriState(1); public static readonly TriState True = new TriState(2); - private TriState(byte value) - { - _value = value; - } + private TriState(byte value) => _value = value; - public bool IsDefault - { - get { return this == Default; } - } + public bool IsDefault => this == Default; - public bool IsFalse - { - get { return this == False; } - } + public bool IsFalse => this == False; - public bool IsNotDefault - { - get { return this != Default; } - } + public bool IsNotDefault => this != Default; - public bool IsTrue - { - get { return this == True; } - } + public bool IsTrue => this == True; - public static bool operator ==(TriState left, TriState right) - { - return left._value == right._value; - } + public static bool operator ==(TriState left, TriState right) => left.Equals(right); - public static bool operator !=(TriState left, TriState right) - { - return !(left == right); - } + public static bool operator !=(TriState left, TriState right) => !left.Equals(right); - public override bool Equals(object? o) + public override bool Equals([NotNullWhen(true)] object? o) { - TriState state = (TriState)o!; - return _value == state._value; + Debug.Assert(o is TriState); + return Equals((TriState)o); } - public override int GetHashCode() - { - return _value; - } + public bool Equals(TriState other) => _value == other._value; - public static implicit operator TriState(bool value) - { - return (value) ? True : False; - } + public override int GetHashCode() => _value; + + public static implicit operator TriState(bool value) => value ? True : False; public static explicit operator bool(TriState value) { if (value.IsDefault) + { throw new InvalidCastException(SR.TriStateCompareError); - else - return (value == TriState.True); - } + } - /// - /// Provides some interesting information about the TriState in String form. - /// - public override string ToString() - { - if (this == Default) return "Default"; - else if (this == False) return "False"; - else return "True"; + return (value == TriState.True); } + + /// Provides some interesting information about the TriState in String form. + public override string ToString() => + this == Default ? "Default" : + this == False ? "False" : + "True"; } } diff --git a/src/libraries/System.Drawing.Common/tests/CharacterRangeTests.cs b/src/libraries/System.Drawing.Common/tests/CharacterRangeTests.cs index 7147cb809be6b..989ee85c09312 100644 --- a/src/libraries/System.Drawing.Common/tests/CharacterRangeTests.cs +++ b/src/libraries/System.Drawing.Common/tests/CharacterRangeTests.cs @@ -84,6 +84,7 @@ public void Equals_Invoke_ReturnsExpected(CharacterRange range, object obj, bool Assert.Equal(expected, range.Equals(obj)); if (obj is CharacterRange otherRange) { + Assert.Equal(expected, range.Equals(otherRange)); Assert.Equal(expected, range == otherRange); Assert.Equal(!expected, range != otherRange); Assert.Equal(expected, range.GetHashCode().Equals(otherRange.GetHashCode())); diff --git a/src/libraries/System.IO.Packaging/src/System/IO/Packaging/PackUriHelper.cs b/src/libraries/System.IO.Packaging/src/System/IO/Packaging/PackUriHelper.cs index 15c89947da327..5825a149f3315 100644 --- a/src/libraries/System.IO.Packaging/src/System/IO/Packaging/PackUriHelper.cs +++ b/src/libraries/System.IO.Packaging/src/System/IO/Packaging/PackUriHelper.cs @@ -611,7 +611,9 @@ private static bool IsPartNameEmpty(string partName) /// to reduce the parsing and number of allocations for Strings and Uris /// we cache the results after parsing. /// + #pragma warning disable CA1067 // Override Equals because it implements IEquatable; not overriding to avoid possible regressions in code that's working internal sealed class ValidatedPartUri : Uri, IComparable, IEquatable +#pragma warning restore CA1067 { //------------------------------------------------------ // diff --git a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LocalVariables.cs b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LocalVariables.cs index d078d82a597f4..f42254df42dd3 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LocalVariables.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LocalVariables.cs @@ -44,7 +44,7 @@ internal LocalVariable(int index, bool closure) string.Create(CultureInfo.InvariantCulture, $"{Index}: {(IsBoxed ? "boxed" : null)} {(InClosure ? "in closure" : null)}"); } - internal readonly struct LocalDefinition + internal readonly struct LocalDefinition : IEquatable { internal LocalDefinition(int localIndex, ParameterExpression parameter) { @@ -53,27 +53,14 @@ internal LocalDefinition(int localIndex, ParameterExpression parameter) } public int Index { get; } + public ParameterExpression Parameter { get; } - public override bool Equals([NotNullWhen(true)] object? obj) - { - if (obj is LocalDefinition) - { - LocalDefinition other = (LocalDefinition)obj; - return other.Index == Index && other.Parameter == Parameter; - } + public override bool Equals([NotNullWhen(true)] object? obj) => obj is LocalDefinition other && Equals(other); - return false; - } + public bool Equals(LocalDefinition other) => other.Index == Index && other.Parameter == Parameter; - public override int GetHashCode() - { - if (Parameter == null) - { - return 0; - } - return Parameter.GetHashCode() ^ Index.GetHashCode(); - } + public override int GetHashCode() => Parameter is null ? 0 : Parameter.GetHashCode() ^ Index.GetHashCode(); } internal sealed class LocalVariables diff --git a/src/libraries/System.Net.Sockets/ref/System.Net.Sockets.cs b/src/libraries/System.Net.Sockets/ref/System.Net.Sockets.cs index 212c063b3b330..e813cca044ee0 100644 --- a/src/libraries/System.Net.Sockets/ref/System.Net.Sockets.cs +++ b/src/libraries/System.Net.Sockets/ref/System.Net.Sockets.cs @@ -74,13 +74,14 @@ public enum IOControlCode : long [System.Runtime.Versioning.SupportedOSPlatformAttribute("windows")] AddressListSort = (long)3355443225, } - public partial struct IPPacketInformation + public partial struct IPPacketInformation : System.IEquatable { private object _dummy; private int _dummyPrimitive; public System.Net.IPAddress Address { get { throw null; } } public int Interface { get { throw null; } } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhen(true)] object? comparand) { throw null; } + public bool Equals(System.Net.Sockets.IPPacketInformation other) { throw null; } public override int GetHashCode() { throw null; } public static bool operator ==(System.Net.Sockets.IPPacketInformation packetInformation1, System.Net.Sockets.IPPacketInformation packetInformation2) { throw null; } public static bool operator !=(System.Net.Sockets.IPPacketInformation packetInformation1, System.Net.Sockets.IPPacketInformation packetInformation2) { throw null; } diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/IPPacketInformation.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/IPPacketInformation.cs index 06d4eca31750b..b0597b626c480 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/IPPacketInformation.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/IPPacketInformation.cs @@ -5,7 +5,7 @@ namespace System.Net.Sockets { - public struct IPPacketInformation + public struct IPPacketInformation : IEquatable { private readonly IPAddress _address; private readonly int _networkInterface; @@ -16,41 +16,27 @@ internal IPPacketInformation(IPAddress address, int networkInterface) _networkInterface = networkInterface; } - public IPAddress Address - { - get - { - return _address; - } - } + public IPAddress Address => _address; - public int Interface - { - get - { - return _networkInterface; - } - } + public int Interface => _networkInterface; - public static bool operator ==(IPPacketInformation packetInformation1, IPPacketInformation packetInformation2) - { - return packetInformation1._networkInterface == packetInformation2._networkInterface && - ((packetInformation1._address == null && packetInformation2._address == null) || - (packetInformation1._address != null && packetInformation1._address.Equals(packetInformation2._address))); - } + public static bool operator ==(IPPacketInformation packetInformation1, IPPacketInformation packetInformation2) => + packetInformation1.Equals(packetInformation2); - public static bool operator !=(IPPacketInformation packetInformation1, IPPacketInformation packetInformation2) - { - return !(packetInformation1 == packetInformation2); - } + public static bool operator !=(IPPacketInformation packetInformation1, IPPacketInformation packetInformation2) => + !packetInformation1.Equals(packetInformation2); public override bool Equals([NotNullWhen(true)] object? comparand) => - comparand is IPPacketInformation other && this == other; + comparand is IPPacketInformation other && Equals(other); - public override int GetHashCode() - { - return unchecked(_networkInterface.GetHashCode() * (int)0xA5555529) + - (_address == null ? 0 : _address.GetHashCode()); - } + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(IPPacketInformation other) => + _networkInterface == other._networkInterface && + (_address is null ? other._address is null : _address.Equals(other._address)); + + public override int GetHashCode() => + unchecked(_networkInterface.GetHashCode() * (int)0xA5555529) + (_address?.GetHashCode() ?? 0); } } diff --git a/src/libraries/System.Net.Sockets/tests/FunctionalTests/IPPacketInformationTest.cs b/src/libraries/System.Net.Sockets/tests/FunctionalTests/IPPacketInformationTest.cs index 443924b66d2b4..19dbc7f470d00 100644 --- a/src/libraries/System.Net.Sockets/tests/FunctionalTests/IPPacketInformationTest.cs +++ b/src/libraries/System.Net.Sockets/tests/FunctionalTests/IPPacketInformationTest.cs @@ -13,7 +13,10 @@ public class IPPacketInformationTest public void Equals_DefaultValues_Success() { Assert.Equal(default(IPPacketInformation), default(IPPacketInformation)); + Assert.True(default(IPPacketInformation) == default(IPPacketInformation)); + Assert.True(default(IPPacketInformation).Equals(default(IPPacketInformation))); + Assert.False(default(IPPacketInformation) != default(IPPacketInformation)); } @@ -31,10 +34,14 @@ public void Equals_NonDefaultValue_Success() Assert.Equal(packetInfo, packetInfoCopy); Assert.True(packetInfo == packetInfoCopy); + Assert.True(packetInfo.Equals(packetInfoCopy)); + Assert.True(packetInfo.Equals((object)packetInfoCopy)); Assert.False(packetInfo != packetInfoCopy); Assert.NotEqual(default, packetInfo); Assert.False(packetInfo == default(IPPacketInformation)); + Assert.False(packetInfo.Equals(default(IPPacketInformation))); + Assert.False(packetInfo.Equals((object)default(IPPacketInformation))); Assert.True(packetInfo != default(IPPacketInformation)); int ignored = packetInfo.Interface; // just make sure it doesn't throw, nothing else to verify diff --git a/src/libraries/System.Private.CoreLib/src/System/ArraySegment.cs b/src/libraries/System.Private.CoreLib/src/System/ArraySegment.cs index 06c31c4d6e009..2d6c817b87268 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ArraySegment.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ArraySegment.cs @@ -26,8 +26,16 @@ namespace System // (ie, users could assign a new value to the old location). [Serializable] [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] +#pragma warning disable CA1066 // adding IEquatable implementation could change semantics of code like that in xunit that queries for IEquatable vs enumerating contents public readonly struct ArraySegment : IList, IReadOnlyList +#pragma warning restore CA1066 { + // ArraySegment doesn't implement IEquatable, even though it provides a strongly-typed + // Equals(T), as that results in different comparison semantics than comparing item-by-item + // the elements returned from its IEnumerable implementation. This then is a breaking change + // for usage like that in xunit's Assert.Equal, which will prioritize using an instance's IEquatable + // over its IEnumerable. + // Do not replace the array allocation with Array.Empty. We don't want to have the overhead of // instantiating another generic type in addition to ArraySegment for new type parameters. #pragma warning disable CA1825 @@ -120,7 +128,7 @@ public void CopyTo(ArraySegment destination) } public override bool Equals([NotNullWhen(true)] object? obj) => - obj is ArraySegment && Equals((ArraySegment)obj); + obj is ArraySegment other && Equals(other); public bool Equals(ArraySegment obj) => obj._array == _array && obj._offset == _offset && obj._count == _count; diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventDescriptor.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventDescriptor.cs index c3994e613a316..b1aaccd7f7f7c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventDescriptor.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventDescriptor.cs @@ -15,7 +15,7 @@ namespace System.Diagnostics.Tracing #if ES_BUILD_STANDALONE [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)] #endif - internal struct EventDescriptor + internal readonly struct EventDescriptor : IEquatable { #region private [FieldOffset(0)] diff --git a/src/libraries/System.Private.CoreLib/src/System/HashCode.cs b/src/libraries/System.Private.CoreLib/src/System/HashCode.cs index d9735f05b4434..f40830e416d36 100644 --- a/src/libraries/System.Private.CoreLib/src/System/HashCode.cs +++ b/src/libraries/System.Private.CoreLib/src/System/HashCode.cs @@ -47,6 +47,8 @@ using System.Runtime.InteropServices; using Internal.Runtime.CompilerServices; +#pragma warning disable CA1066 // Implement IEquatable when overriding Object.Equals + namespace System { // xxHash32 is used for the hash code. diff --git a/src/libraries/System.Private.CoreLib/src/System/IntPtr.cs b/src/libraries/System.Private.CoreLib/src/System/IntPtr.cs index 7fb1803d6f5ab..355578395db40 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IntPtr.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IntPtr.cs @@ -11,6 +11,8 @@ using Internal.Runtime.CompilerServices; #pragma warning disable SA1121 // explicitly using type aliases instead of built-in types +#pragma warning disable CA1066 // Implement IEquatable when overriding Object.Equals + #if TARGET_64BIT using nint_t = System.Int64; #else diff --git a/src/libraries/System.Private.CoreLib/src/System/Nullable.cs b/src/libraries/System.Private.CoreLib/src/System/Nullable.cs index 0fa9141483ee2..089f970057dc8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Nullable.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Nullable.cs @@ -4,6 +4,8 @@ using System.Collections.Generic; using System.Runtime.Versioning; +#pragma warning disable CA1066 // Implement IEquatable when overriding Object.Equals + namespace System { // Because we have special type system support that says a boxed Nullable diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/CustomAttributeNamedArgument.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/CustomAttributeNamedArgument.cs index 9699e14e5d1e5..b2baa777460a6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/CustomAttributeNamedArgument.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/CustomAttributeNamedArgument.cs @@ -1,9 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; + namespace System.Reflection { - public readonly partial struct CustomAttributeNamedArgument + public readonly partial struct CustomAttributeNamedArgument : IEquatable { public static bool operator ==(CustomAttributeNamedArgument left, CustomAttributeNamedArgument right) => left.Equals(right); public static bool operator !=(CustomAttributeNamedArgument left, CustomAttributeNamedArgument right) => !left.Equals(right); @@ -46,10 +48,15 @@ public override int GetHashCode() return base.GetHashCode(); } - public override bool Equals(object? obj) - { - return obj == (object)this; - } + public override bool Equals([NotNullWhen(true)] object? obj) => + obj is CustomAttributeNamedArgument other && Equals(other); + + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(CustomAttributeNamedArgument other) => + _memberInfo == other._memberInfo && + _value == other._value; internal Type ArgumentType => _memberInfo is FieldInfo fi ? diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/CustomAttributeTypedArgument.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/CustomAttributeTypedArgument.cs index 3198e9fd45802..b0e306af8f838 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/CustomAttributeTypedArgument.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/CustomAttributeTypedArgument.cs @@ -2,11 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Text; namespace System.Reflection { - public readonly partial struct CustomAttributeTypedArgument + public readonly partial struct CustomAttributeTypedArgument : IEquatable { public static bool operator ==(CustomAttributeTypedArgument left, CustomAttributeTypedArgument right) => left.Equals(right); public static bool operator !=(CustomAttributeTypedArgument left, CustomAttributeTypedArgument right) => !left.Equals(right); @@ -86,7 +87,13 @@ internal string ToString(bool typed) } public override int GetHashCode() => base.GetHashCode(); - public override bool Equals(object? obj) => obj == (object)this; + + public override bool Equals([NotNullWhen(true)] object? obj) => obj is CustomAttributeTypedArgument cata && Equals(cata); + + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(CustomAttributeTypedArgument other) => _value == other._value && _argumentType == other._argumentType; public Type ArgumentType => _argumentType; public object? Value => _value; diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ArrayWithOffset.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ArrayWithOffset.cs index 8a80faa9977b6..92d42d6795567 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ArrayWithOffset.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ArrayWithOffset.cs @@ -6,7 +6,7 @@ namespace System.Runtime.InteropServices { - public readonly struct ArrayWithOffset + public readonly struct ArrayWithOffset : IEquatable { private readonly object? m_array; private readonly int m_offset; @@ -52,7 +52,7 @@ public ArrayWithOffset(object? array, int offset) public override bool Equals([NotNullWhen(true)] object? obj) { - return obj is ArrayWithOffset && Equals((ArrayWithOffset)obj); + return obj is ArrayWithOffset awo && Equals(awo); } public bool Equals(ArrayWithOffset obj) diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.cs index 579633db55caf..a1c849b48c71b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.cs @@ -23,7 +23,7 @@ namespace System.Runtime.InteropServices /// Pinned - same as Normal, but allows the address of the actual object to be taken. /// [StructLayout(LayoutKind.Sequential)] - public partial struct GCHandle + public partial struct GCHandle : IEquatable { // The actual integer handle value that the EE uses internally. private IntPtr _handle; @@ -163,7 +163,12 @@ public static GCHandle FromIntPtr(IntPtr value) public override int GetHashCode() => _handle.GetHashCode(); - public override bool Equals([NotNullWhen(true)] object? o) => o is GCHandle && _handle == ((GCHandle)o)._handle; + public override bool Equals([NotNullWhen(true)] object? o) => o is GCHandle other && Equals(other); + + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(GCHandle other) => _handle == other._handle; public static bool operator ==(GCHandle a, GCHandle b) => (nint)a._handle == (nint)b._handle; diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Serialization/StreamingContext.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Serialization/StreamingContext.cs index 3501457fa82d1..1b3b86c0b9a64 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Serialization/StreamingContext.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Serialization/StreamingContext.cs @@ -3,6 +3,8 @@ using System.Diagnostics.CodeAnalysis; +#pragma warning disable CA1066 // Implement IEquatable when overriding Object.Equals + namespace System.Runtime.Serialization { public readonly struct StreamingContext diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationToken.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationToken.cs index ab03e12e87be0..27f29cb0dd949 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationToken.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationToken.cs @@ -27,7 +27,7 @@ namespace System.Threading /// /// [DebuggerDisplay("IsCancellationRequested = {IsCancellationRequested}")] - public readonly struct CancellationToken + public readonly struct CancellationToken : IEquatable { // The backing TokenSource. // if null, it implicitly represents the same thing as new CancellationToken(false). diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/LowLevelLifoSemaphore.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/LowLevelLifoSemaphore.cs index 6b6b86eb28b71..25a229c87ef66 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/LowLevelLifoSemaphore.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/LowLevelLifoSemaphore.cs @@ -242,7 +242,7 @@ private bool WaitForSignal(int timeoutMs) } } - private struct Counts + private struct Counts : IEquatable { private const byte SignalCountShift = 0; private const byte WaiterCountShift = 32; @@ -350,10 +350,11 @@ public void DecrementCountOfWaitersSignaledToWake() public Counts InterlockedCompareExchange(Counts newCounts, Counts oldCounts) => new Counts(Interlocked.CompareExchange(ref _data, newCounts._data, oldCounts._data)); - public static bool operator ==(Counts lhs, Counts rhs) => lhs._data == rhs._data; - public static bool operator !=(Counts lhs, Counts rhs) => lhs._data != rhs._data; + public static bool operator ==(Counts lhs, Counts rhs) => lhs.Equals(rhs); + public static bool operator !=(Counts lhs, Counts rhs) => !lhs.Equals(rhs); - public override bool Equals([NotNullWhen(true)] object? obj) => obj is Counts counts && _data == counts._data; + public override bool Equals([NotNullWhen(true)] object? obj) => obj is Counts other && Equals(other); + public bool Equals(Counts other) => _data == other._data; public override int GetHashCode() => (int)_data + (int)(_data >> 32); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.ThreadCounts.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.ThreadCounts.cs index 43aa0fcf7102c..3242f165aff9a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.ThreadCounts.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.ThreadCounts.cs @@ -11,7 +11,7 @@ internal sealed partial class PortableThreadPool /// /// Tracks information on the number of threads we want/have in different states in our thread pool. /// - private struct ThreadCounts + private struct ThreadCounts : IEquatable { // SOS's ThreadPool command depends on this layout private const byte NumProcessingWorkShift = 0; @@ -126,7 +126,8 @@ public ThreadCounts InterlockedCompareExchange(ThreadCounts newCounts, ThreadCou public static bool operator ==(ThreadCounts lhs, ThreadCounts rhs) => lhs._data == rhs._data; public static bool operator !=(ThreadCounts lhs, ThreadCounts rhs) => lhs._data != rhs._data; - public override bool Equals([NotNullWhen(true)] object? obj) => obj is ThreadCounts other && _data == other._data; + public override bool Equals([NotNullWhen(true)] object? obj) => obj is ThreadCounts other && Equals(other); + public bool Equals(ThreadCounts other) => _data == other._data; public override int GetHashCode() => (int)_data + (int)(_data >> 32); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.WorkerTracking.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.WorkerTracking.cs index 8c588965add43..8a5f1d8bba581 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.WorkerTracking.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.WorkerTracking.cs @@ -58,7 +58,7 @@ private short GetAndResetHighWatermarkCountOfThreadsProcessingUserCallbacks() /// /// Tracks thread count information that is used when the EnableWorkerTracking config option is enabled. /// - private struct CountsOfThreadsProcessingUserCallbacks + private struct CountsOfThreadsProcessingUserCallbacks : IEquatable { private const byte CurrentShift = 0; private const byte HighWatermarkShift = 16; @@ -114,13 +114,16 @@ public void DecrementCurrent() public static bool operator ==( CountsOfThreadsProcessingUserCallbacks lhs, - CountsOfThreadsProcessingUserCallbacks rhs) => lhs._data == rhs._data; + CountsOfThreadsProcessingUserCallbacks rhs) => lhs.Equals(rhs); public static bool operator !=( CountsOfThreadsProcessingUserCallbacks lhs, - CountsOfThreadsProcessingUserCallbacks rhs) => lhs._data != rhs._data; + CountsOfThreadsProcessingUserCallbacks rhs) => !lhs.Equals(rhs); public override bool Equals([NotNullWhen(true)] object? obj) => - obj is CountsOfThreadsProcessingUserCallbacks other && _data == other._data; + obj is CountsOfThreadsProcessingUserCallbacks other && Equals(other); + + public bool Equals(CountsOfThreadsProcessingUserCallbacks other) => _data == other._data; + public override int GetHashCode() => (int)_data; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.AdjustmentRule.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.AdjustmentRule.cs index 6f53ab75ce351..7c754b4f28570 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.AdjustmentRule.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.AdjustmentRule.cs @@ -56,6 +56,12 @@ public sealed class AdjustmentRule : IEquatable, ISerializable, _daylightTransitionEnd.Equals(other._daylightTransitionEnd) && _daylightTransitionStart.Equals(other._daylightTransitionStart); + /// Indicates whether the current instance is equal to another instance. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public override bool Equals([NotNullWhen(true)] object? obj) => + obj is AdjustmentRule other && Equals(other); + public override int GetHashCode() => _dateStart.GetHashCode(); private AdjustmentRule( diff --git a/src/libraries/System.Private.CoreLib/src/System/UIntPtr.cs b/src/libraries/System.Private.CoreLib/src/System/UIntPtr.cs index bc7859c0d18d9..12a2dce1d7258 100644 --- a/src/libraries/System.Private.CoreLib/src/System/UIntPtr.cs +++ b/src/libraries/System.Private.CoreLib/src/System/UIntPtr.cs @@ -11,6 +11,8 @@ using Internal.Runtime.CompilerServices; #pragma warning disable SA1121 // explicitly using type aliases instead of built-in types +#pragma warning disable CA1066 // Implement IEquatable when overriding Object.Equals + #if TARGET_64BIT using nuint_t = System.UInt64; #else diff --git a/src/libraries/System.Private.Xml/src/System/Xml/BinaryXml/XmlBinaryReader.cs b/src/libraries/System.Private.Xml/src/System/Xml/BinaryXml/XmlBinaryReader.cs index 074f795ea54c0..33d1e3dff11c2 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/BinaryXml/XmlBinaryReader.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/BinaryXml/XmlBinaryReader.cs @@ -59,7 +59,7 @@ private enum ScanState }; // Note: also used by XmlBinaryWriter - internal struct QName + internal struct QName : IEquatable { public string prefix; public string localname; @@ -95,45 +95,26 @@ public void CheckPrefixNS(string prefix, string namespaceUri) throw new XmlException(SR.XmlBinary_NoRemapPrefix, new string[] { prefix, this.namespaceUri, namespaceUri }); } - public override int GetHashCode() - { - return this.prefix.GetHashCode() ^ this.localname.GetHashCode(); - } + public int GetNSHashCode() => + HashCode.Combine(this.namespaceUri, this.localname); - public int GetNSHashCode() - { - return HashCode.Combine(this.namespaceUri, this.localname); - } + public override int GetHashCode() => + this.prefix.GetHashCode() ^ this.localname.GetHashCode(); + public override bool Equals([NotNullWhen(true)] object? other) => + other is QName qname && Equals(qname); - public override bool Equals([NotNullWhen(true)] object? other) - { - if (other is QName that) - { - return this == that; - } - return false; - } + public bool Equals(QName other) => + prefix == other.prefix && + localname == other.localname && + namespaceUri == other.namespaceUri; - public override string ToString() - { - if (prefix.Length == 0) - return this.localname; - else - return $"{this.prefix}:{this.localname}"; - } + public static bool operator ==(QName a, QName b) => a.Equals(b); - public static bool operator ==(QName a, QName b) - { - return ((a.prefix == b.prefix) - && (a.localname == b.localname) - && (a.namespaceUri == b.namespaceUri)); - } + public static bool operator !=(QName a, QName b) => !a.Equals(b); - public static bool operator !=(QName a, QName b) - { - return !(a == b); - } + public override string ToString() => + prefix.Length == 0 ? localname : $"{this.prefix}:{this.localname}"; }; private struct ElemInfo diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Pair.cs b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Pair.cs index 8e3e1a4b841a7..33b4fe98b3f92 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Pair.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Pair.cs @@ -7,49 +7,34 @@ namespace System.Xml.Xsl { - internal struct Int32Pair + internal readonly struct Int32Pair : IEquatable { - private readonly int _left; - private readonly int _right; - public Int32Pair(int left, int right) { - _left = left; - _right = right; + Left = left; + Right = right; } - public int Left { get { return _left; } } - public int Right { get { return _right; } } + public int Left { get; } + public int Right { get; } - public override bool Equals([NotNullWhen(true)] object? other) - { - if (other is Int32Pair) - { - Int32Pair o = (Int32Pair)other; - return _left == o._left && _right == o._right; - } + public override bool Equals([NotNullWhen(true)] object? other) => + other is Int32Pair o && Equals(o); - return false; - } + public bool Equals(Int32Pair other) => Left == other.Left && Right == other.Right; - public override int GetHashCode() - { - return _left.GetHashCode() ^ _right.GetHashCode(); - } + public override int GetHashCode() => Left.GetHashCode() ^ Right.GetHashCode(); } - internal struct StringPair + internal readonly struct StringPair { - private readonly string _left; - private readonly string _right; - public StringPair(string left, string right) { - _left = left; - _right = right; + Left = left; + Right = right; } - public string Left { get { return _left; } } - public string Right { get { return _right; } } + public string Left { get; } + public string Right { get; } } } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XmlQueryCardinality.cs b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XmlQueryCardinality.cs index 1046765a2d3b2..a95ce13c1737c 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XmlQueryCardinality.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XmlQueryCardinality.cs @@ -11,7 +11,7 @@ namespace System.Xml.Xsl /// Cardinality of part of XmlQueryType /// struct is being used because enum doesn't allow members /// - internal struct XmlQueryCardinality + internal readonly struct XmlQueryCardinality : IEquatable { private readonly int _value; diff --git a/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/CacheExpires.cs b/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/CacheExpires.cs index e4eab06b7adb3..f9cc0fd36dadf 100644 --- a/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/CacheExpires.cs +++ b/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/CacheExpires.cs @@ -13,7 +13,7 @@ namespace System.Runtime.Caching { - internal struct ExpiresEntryRef + internal readonly struct ExpiresEntryRef : IEquatable { internal static readonly ExpiresEntryRef INVALID = new ExpiresEntryRef(0, 0); @@ -31,55 +31,18 @@ internal ExpiresEntryRef(int pageIndex, int entryIndex) _ref = ((((uint)pageIndex) << PAGE_SHIFT) | (((uint)(entryIndex)) & ENTRY_MASK)); } - public override bool Equals(object value) - { - if (value is ExpiresEntryRef) - { - return _ref == ((ExpiresEntryRef)value)._ref; - } + public override bool Equals(object value) => value is ExpiresEntryRef other && Equals(other); - return false; - } + public bool Equals(ExpiresEntryRef other) => _ref == other._ref; - public static bool operator !=(ExpiresEntryRef r1, ExpiresEntryRef r2) - { - return r1._ref != r2._ref; - } - public static bool operator ==(ExpiresEntryRef r1, ExpiresEntryRef r2) - { - return r1._ref == r2._ref; - } + public static bool operator ==(ExpiresEntryRef r1, ExpiresEntryRef r2) => r1.Equals(r2); + public static bool operator !=(ExpiresEntryRef r1, ExpiresEntryRef r2) => !r1.Equals(r2); - public override int GetHashCode() - { - return (int)_ref; - } + public override int GetHashCode() => (int)_ref; - internal int PageIndex - { - get - { - int result = (int)(_ref >> PAGE_SHIFT); - return result; - } - } - - internal int Index - { - get - { - int result = (int)(_ref & ENTRY_MASK); - return result; - } - } - - internal bool IsInvalid - { - get - { - return _ref == 0; - } - } + internal int PageIndex => (int)(_ref >> PAGE_SHIFT); + internal int Index => (int)(_ref & ENTRY_MASK); + internal bool IsInvalid => _ref == 0; } [StructLayout(LayoutKind.Explicit)] diff --git a/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/CacheUsage.cs b/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/CacheUsage.cs index 73ed9f30d3d5c..7b7ea64279211 100644 --- a/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/CacheUsage.cs +++ b/src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/CacheUsage.cs @@ -13,7 +13,7 @@ namespace System.Runtime.Caching { - internal struct UsageEntryRef + internal readonly struct UsageEntryRef : IEquatable { internal static readonly UsageEntryRef INVALID = new UsageEntryRef(0, 0); @@ -31,38 +31,18 @@ internal UsageEntryRef(int pageIndex, int entryIndex) _ref = ((((uint)pageIndex) << PAGE_SHIFT) | (((uint)(entryIndex)) & ENTRY_MASK)); } - public override bool Equals(object value) - { - if (value is UsageEntryRef) - { - return _ref == ((UsageEntryRef)value)._ref; - } + public override bool Equals(object value) => + value is UsageEntryRef other && Equals(other); - return false; - } - public static bool operator ==(UsageEntryRef r1, UsageEntryRef r2) - { - return r1._ref == r2._ref; - } + public bool Equals(UsageEntryRef other) => _ref == other._ref; - public static bool operator !=(UsageEntryRef r1, UsageEntryRef r2) - { - return r1._ref != r2._ref; - } + public static bool operator ==(UsageEntryRef r1, UsageEntryRef r2) => r1.Equals(r2); - public override int GetHashCode() - { - return (int)_ref; - } + public static bool operator !=(UsageEntryRef r1, UsageEntryRef r2) => !r1.Equals(r2); - internal int PageIndex - { - get - { - int result = (int)(_ref >> PAGE_SHIFT); - return result; - } - } + public override int GetHashCode() => (int)_ref; + + internal int PageIndex => (int)(_ref >> PAGE_SHIFT); internal int Ref1Index { @@ -84,29 +64,11 @@ internal int Ref2Index } } - internal bool IsRef1 - { - get - { - return ((int)(sbyte)(_ref & ENTRY_MASK)) > 0; - } - } + internal bool IsRef1 => ((int)(sbyte)(_ref & ENTRY_MASK)) > 0; - internal bool IsRef2 - { - get - { - return ((int)(sbyte)(_ref & ENTRY_MASK)) < 0; - } - } + internal bool IsRef2 => ((int)(sbyte)(_ref & ENTRY_MASK)) < 0; - internal bool IsInvalid - { - get - { - return _ref == 0; - } - } + internal bool IsInvalid => _ref == 0; } internal struct UsageEntryLink diff --git a/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs b/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs index 901b76346b82c..e58de5b8a040a 100644 --- a/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs +++ b/src/libraries/System.Runtime.InteropServices/ref/System.Runtime.InteropServices.cs @@ -98,7 +98,7 @@ public sealed partial class AllowReversePInvokeCallsAttribute : System.Attribute { public AllowReversePInvokeCallsAttribute() { } } - public readonly partial struct ArrayWithOffset + public readonly partial struct ArrayWithOffset : System.IEquatable { private readonly object _dummy; private readonly int _dummyPrimitive; diff --git a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/GCHandleTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/GCHandleTests.cs index bf5ec1713cdbc..8a79b7a66db45 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/GCHandleTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/GCHandleTests.cs @@ -138,6 +138,7 @@ public void Equals_Object_ReturnsExpected(GCHandle handle, object other, bool ex Assert.Equal(expected, handle.Equals(other)); if (other is GCHandle otherHandle) { + Assert.Equal(expected, handle.Equals(otherHandle)); Assert.Equal(expected, handle == otherHandle); Assert.Equal(!expected, handle != otherHandle); } diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index c57c5b13cc119..57c9f8368994e 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -4826,7 +4826,7 @@ public partial class MissingMethodException : System.MissingMemberException public MissingMethodException(string? className, string? methodName) { } public override string Message { get { throw null; } } } - public partial struct ModuleHandle + public partial struct ModuleHandle : System.IEquatable { private object _dummy; private int _dummyPrimitive; @@ -6367,6 +6367,7 @@ public sealed partial class AdjustmentRule : System.IEquatable { private readonly object _dummy; private readonly int _dummyPrimitive; @@ -11658,13 +11659,14 @@ public partial class CustomAttributeFormatException : System.FormatException public System.Reflection.MemberInfo MemberInfo { get { throw null; } } public string MemberName { get { throw null; } } public System.Reflection.CustomAttributeTypedArgument TypedValue { get { throw null; } } - public override bool Equals(object? obj) { throw null; } + public bool Equals(System.Reflection.CustomAttributeNamedArgument other) { throw null; } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } public override int GetHashCode() { throw null; } public static bool operator ==(System.Reflection.CustomAttributeNamedArgument left, System.Reflection.CustomAttributeNamedArgument right) { throw null; } public static bool operator !=(System.Reflection.CustomAttributeNamedArgument left, System.Reflection.CustomAttributeNamedArgument right) { throw null; } public override string ToString() { throw null; } } - public readonly partial struct CustomAttributeTypedArgument + public readonly partial struct CustomAttributeTypedArgument : System.IEquatable { private readonly object _dummy; private readonly int _dummyPrimitive; @@ -11672,7 +11674,8 @@ public partial class CustomAttributeFormatException : System.FormatException public CustomAttributeTypedArgument(System.Type argumentType, object? value) { throw null; } public System.Type ArgumentType { get { throw null; } } public object? Value { get { throw null; } } - public override bool Equals(object? obj) { throw null; } + public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } + public bool Equals(System.Reflection.CustomAttributeTypedArgument other) { throw null; } public override int GetHashCode() { throw null; } public static bool operator ==(System.Reflection.CustomAttributeTypedArgument left, System.Reflection.CustomAttributeTypedArgument right) { throw null; } public static bool operator !=(System.Reflection.CustomAttributeTypedArgument left, System.Reflection.CustomAttributeTypedArgument right) { throw null; } @@ -13493,7 +13496,7 @@ public sealed partial class FieldOffsetAttribute : System.Attribute public FieldOffsetAttribute(int offset) { } public int Value { get { throw null; } } } - public partial struct GCHandle + public partial struct GCHandle : System.IEquatable { private int _dummyPrimitive; public bool IsAllocated { get { throw null; } } @@ -13502,6 +13505,7 @@ public partial struct GCHandle public static System.Runtime.InteropServices.GCHandle Alloc(object? value) { throw null; } public static System.Runtime.InteropServices.GCHandle Alloc(object? value, System.Runtime.InteropServices.GCHandleType type) { throw null; } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? o) { throw null; } + public bool Equals(System.Runtime.InteropServices.GCHandle other) { throw null; } public void Free() { } public static System.Runtime.InteropServices.GCHandle FromIntPtr(System.IntPtr value) { throw null; } public override int GetHashCode() { throw null; } @@ -14770,7 +14774,7 @@ public static partial class Utf8 } namespace System.Threading { - public readonly partial struct CancellationToken + public readonly partial struct CancellationToken : System.IEquatable { private readonly object _dummy; private readonly int _dummyPrimitive; diff --git a/src/libraries/System.Runtime/tests/System/Reflection/CustomAttribute_Named_Typed_ArgumentTests.cs b/src/libraries/System.Runtime/tests/System/Reflection/CustomAttribute_Named_Typed_ArgumentTests.cs index 4460797182c87..c406e36ea21c3 100644 --- a/src/libraries/System.Runtime/tests/System/Reflection/CustomAttribute_Named_Typed_ArgumentTests.cs +++ b/src/libraries/System.Runtime/tests/System/Reflection/CustomAttribute_Named_Typed_ArgumentTests.cs @@ -52,6 +52,28 @@ public static void Test_CustomAttributeTypedArgument_Constructor() Assert.True(false, "Expected to find MyAttr Attribute"); } + [Fact] + public static void Test_CustomAttributeTypedArgument_Equals() + { + Type t = typeof(MyClass); + foreach (CustomAttributeData cad in CustomAttributeData.GetCustomAttributes(t)) + { + foreach (CustomAttributeTypedArgument cata in cad.ConstructorArguments) + { + Assert.True(cata.Equals(cata)); + Assert.True(cata.Equals((object)cata)); + + var notEqualArgument = new CustomAttributeTypedArgument(new [] { new CustomAttributeTypedArgument(0) }); + Assert.False(cata.Equals(notEqualArgument)); + Assert.False(cata.Equals((object)notEqualArgument)); + + return; + } + } + + Assert.True(false, "Expected to find MyAttr Attribute"); + } + [Fact] public static void Test_CustomAttributeTypedArgument_ToString() { diff --git a/src/libraries/System.ServiceProcess.ServiceController/ref/System.ServiceProcess.ServiceController.netcoreapp.cs b/src/libraries/System.ServiceProcess.ServiceController/ref/System.ServiceProcess.ServiceController.netcoreapp.cs index 3fd806b0f5649..1298a7c23d690 100644 --- a/src/libraries/System.ServiceProcess.ServiceController/ref/System.ServiceProcess.ServiceController.netcoreapp.cs +++ b/src/libraries/System.ServiceProcess.ServiceController/ref/System.ServiceProcess.ServiceController.netcoreapp.cs @@ -10,4 +10,7 @@ public partial class ServiceController : System.ComponentModel.Component { public void Stop(bool stopDependentServices) { } } + public readonly partial struct SessionChangeDescription : System.IEquatable + { + } } diff --git a/src/libraries/System.ServiceProcess.ServiceController/src/System.ServiceProcess.ServiceController.csproj b/src/libraries/System.ServiceProcess.ServiceController/src/System.ServiceProcess.ServiceController.csproj index 8fd0582994dd4..fac46aed04ba2 100644 --- a/src/libraries/System.ServiceProcess.ServiceController/src/System.ServiceProcess.ServiceController.csproj +++ b/src/libraries/System.ServiceProcess.ServiceController/src/System.ServiceProcess.ServiceController.csproj @@ -17,6 +17,8 @@ System.ServiceProcess.ServiceType true true SR.PlatformNotSupported_ServiceController + + $(NoWarn);CA1066 +#endif { internal SessionChangeDescription(SessionChangeReason reason, int id) { @@ -17,34 +20,20 @@ internal SessionChangeDescription(SessionChangeReason reason, int id) public int SessionId { get; } - public override bool Equals([NotNullWhen(true)] object? obj) - { - if (!(obj is SessionChangeDescription)) - { - return false; - } + public override int GetHashCode() => + (int)Reason ^ SessionId; - return Equals((SessionChangeDescription)obj); - } + public override bool Equals([NotNullWhen(true)] object? obj) => + obj is SessionChangeDescription other && Equals(other); - public override int GetHashCode() - { - return (int)Reason ^ SessionId; - } + public bool Equals(SessionChangeDescription changeDescription) => + (Reason == changeDescription.Reason) && + (SessionId == changeDescription.SessionId); - public bool Equals(SessionChangeDescription changeDescription) - { - return (Reason == changeDescription.Reason) && (SessionId == changeDescription.SessionId); - } + public static bool operator ==(SessionChangeDescription a, SessionChangeDescription b) => + a.Equals(b); - public static bool operator ==(SessionChangeDescription a, SessionChangeDescription b) - { - return a.Equals(b); - } - - public static bool operator !=(SessionChangeDescription a, SessionChangeDescription b) - { - return !a.Equals(b); - } + public static bool operator !=(SessionChangeDescription a, SessionChangeDescription b) => + !a.Equals(b); } } diff --git a/src/libraries/System.Speech/src/Internal/Synthesis/EngineSiteSapi.cs b/src/libraries/System.Speech/src/Internal/Synthesis/EngineSiteSapi.cs index d6bf03a57d2f1..e44843b0c8193 100644 --- a/src/libraries/System.Speech/src/Internal/Synthesis/EngineSiteSapi.cs +++ b/src/libraries/System.Speech/src/Internal/Synthesis/EngineSiteSapi.cs @@ -176,8 +176,9 @@ internal interface ISpEngineSite void CompleteSkip(int skipped); void LoadResource([MarshalAs(UnmanagedType.LPWStr)] string resource, ref string mediaType, out IStream stream); } + [StructLayout(LayoutKind.Sequential)] - internal struct SpeechEventSapi + internal struct SpeechEventSapi : IEquatable { public short EventId; public short ParameterType; @@ -185,27 +186,22 @@ internal struct SpeechEventSapi public long AudioStreamOffset; public IntPtr Param1; // Always just a numeric type - contains no unmanaged resources so does not need special clean-up. public IntPtr Param2; // Can be a numeric type, or pointer to string or object. Use SafeSapiLParamHandle to cleanup. - public static bool operator ==(SpeechEventSapi event1, SpeechEventSapi event2) - { - return event1.EventId == event2.EventId && event1.ParameterType == event2.ParameterType && event1.StreamNumber == event2.StreamNumber && event1.AudioStreamOffset == event2.AudioStreamOffset && event1.Param1 == event2.Param1 && event1.Param2 == event2.Param2; - } - public static bool operator !=(SpeechEventSapi event1, SpeechEventSapi event2) - { - return !(event1 == event2); - } - public override bool Equals(object obj) - { - if (!(obj is SpeechEventSapi)) - { - return false; - } - return this == (SpeechEventSapi)obj; - } - public override int GetHashCode() - { - return base.GetHashCode(); - } + public static bool operator ==(SpeechEventSapi event1, SpeechEventSapi event2) => event1.Equals(event2); + public static bool operator !=(SpeechEventSapi event1, SpeechEventSapi event2) => !event1.Equals(event2); + + public override bool Equals(object obj) => + obj is SpeechEventSapi other && Equals(other); + + public bool Equals(SpeechEventSapi other) => + EventId == other.EventId && + ParameterType == other.ParameterType && + StreamNumber == other.StreamNumber && + AudioStreamOffset == other.AudioStreamOffset && + Param1 == other.Param1 && + Param2 == other.Param2; + + public override int GetHashCode() => base.GetHashCode(); } #endregion diff --git a/src/libraries/System.Text.Encodings.Web/src/Polyfills/System.Text.Rune.netstandard20.cs b/src/libraries/System.Text.Encodings.Web/src/Polyfills/System.Text.Rune.netstandard20.cs index 66c637eda2a2b..774ee9e426c7e 100644 --- a/src/libraries/System.Text.Encodings.Web/src/Polyfills/System.Text.Rune.netstandard20.cs +++ b/src/libraries/System.Text.Encodings.Web/src/Polyfills/System.Text.Rune.netstandard20.cs @@ -14,7 +14,7 @@ namespace System.Text { - internal readonly struct Rune + internal readonly struct Rune : IEquatable { private const int MaxUtf16CharsPerRune = 2; // supplementary plane code points are encoded as 2 UTF-16 code units diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Symbolic/SymbolicMatch.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Symbolic/SymbolicMatch.cs index c6754b8577b0d..5ba715c25ef4c 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Symbolic/SymbolicMatch.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Symbolic/SymbolicMatch.cs @@ -5,7 +5,7 @@ namespace System.Text.RegularExpressions.Symbolic { - internal readonly struct SymbolicMatch + internal readonly struct SymbolicMatch : IEquatable { /// Indicates failure to find a match. internal static SymbolicMatch NoMatch => new SymbolicMatch(-1, -1); @@ -20,17 +20,21 @@ public SymbolicMatch(int index, int length) } public int Index { get; } + public int Length { get; } + public bool Success => Index >= 0; public static bool operator ==(SymbolicMatch left, SymbolicMatch right) => - left.Index == right.Index && left.Length == right.Length; + left.Equals(right); public static bool operator !=(SymbolicMatch left, SymbolicMatch right) => - !(left == right); + !left.Equals(right); public override bool Equals([NotNullWhen(true)] object? obj) => - obj is SymbolicMatch other && this == other; + obj is SymbolicMatch other && Equals(other); + + public bool Equals(SymbolicMatch other) => Index == other.Index && Length == other.Length; public override int GetHashCode() => HashCode.Combine(Index, Length); } diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Symbolic/SymbolicRegexInfo.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Symbolic/SymbolicRegexInfo.cs index ba522d513392c..4e60696eb0717 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Symbolic/SymbolicRegexInfo.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Symbolic/SymbolicRegexInfo.cs @@ -4,7 +4,7 @@ namespace System.Text.RegularExpressions.Symbolic { /// Misc information of structural properties of a that is computed bottom up. - internal readonly struct SymbolicRegexInfo + internal readonly struct SymbolicRegexInfo : IEquatable { private const uint IsAlwaysNullableMask = 1; private const uint StartsWithLineAnchorMask = 2; @@ -177,7 +177,9 @@ public static SymbolicRegexInfo Loop(SymbolicRegexInfo body_info, int lowerBound containsSomeCharacter: info.ContainsSomeCharacter, isLazy: info.IsLazy); - public override bool Equals(object? obj) => obj is SymbolicRegexInfo i && i._info == _info; + public override bool Equals(object? obj) => obj is SymbolicRegexInfo i && Equals(i); + + public bool Equals(SymbolicRegexInfo other) => _info == other._info; public override int GetHashCode() => _info.GetHashCode(); diff --git a/src/libraries/System.Threading/ref/System.Threading.cs b/src/libraries/System.Threading/ref/System.Threading.cs index 1237c49cecaed..3c5f1268e8873 100644 --- a/src/libraries/System.Threading/ref/System.Threading.cs +++ b/src/libraries/System.Threading/ref/System.Threading.cs @@ -235,7 +235,7 @@ public static partial class LazyInitializer public static T EnsureInitialized([System.Diagnostics.CodeAnalysis.NotNullAttribute] ref T? target, System.Func valueFactory) where T : class { throw null; } public static T EnsureInitialized([System.Diagnostics.CodeAnalysis.NotNullAttribute] ref T? target, [System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute("syncLock")] ref object? syncLock, System.Func valueFactory) where T : class { throw null; } } - public partial struct LockCookie + public partial struct LockCookie : System.IEquatable { private int _dummyPrimitive; public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } diff --git a/src/libraries/System.Threading/src/System/Threading/LockCookie.cs b/src/libraries/System.Threading/src/System/Threading/LockCookie.cs index 6a76ceb023d0a..a9c9011179f8f 100644 --- a/src/libraries/System.Threading/src/System/Threading/LockCookie.cs +++ b/src/libraries/System.Threading/src/System/Threading/LockCookie.cs @@ -9,40 +9,27 @@ namespace System.Threading /// Stores the lock state of a before its lock state is changed, such that the lock state may /// later be restored. /// - public struct LockCookie + public struct LockCookie : IEquatable { internal LockCookieFlags _flags; internal ushort _readerLevel; internal ushort _writerLevel; internal int _threadID; - public override int GetHashCode() - { - return (int)_flags + _readerLevel + _writerLevel + _threadID; - } + public override int GetHashCode() => + (int)_flags + _readerLevel + _writerLevel + _threadID; - public override bool Equals([NotNullWhen(true)] object? obj) - { - return obj is LockCookie && Equals((LockCookie)obj); - } + public override bool Equals([NotNullWhen(true)] object? obj) => + obj is LockCookie other && Equals(other); - public bool Equals(LockCookie obj) - { - return - _flags == obj._flags && - _readerLevel == obj._readerLevel && - _writerLevel == obj._writerLevel && - _threadID == obj._threadID; - } + public bool Equals(LockCookie obj) => + _flags == obj._flags && + _readerLevel == obj._readerLevel && + _writerLevel == obj._writerLevel && + _threadID == obj._threadID; - public static bool operator ==(LockCookie a, LockCookie b) - { - return a.Equals(b); - } + public static bool operator ==(LockCookie a, LockCookie b) => a.Equals(b); - public static bool operator !=(LockCookie a, LockCookie b) - { - return !(a == b); - } + public static bool operator !=(LockCookie a, LockCookie b) => !a.Equals(b); } } diff --git a/src/libraries/System.Transactions.Local/ref/System.Transactions.Local.cs b/src/libraries/System.Transactions.Local/ref/System.Transactions.Local.cs index 91804388b42fa..f52ae1ffd8b91 100644 --- a/src/libraries/System.Transactions.Local/ref/System.Transactions.Local.cs +++ b/src/libraries/System.Transactions.Local/ref/System.Transactions.Local.cs @@ -202,12 +202,13 @@ public partial class TransactionManagerCommunicationException : System.Transacti public TransactionManagerCommunicationException(string? message) { } public TransactionManagerCommunicationException(string? message, System.Exception? innerException) { } } - public partial struct TransactionOptions + public partial struct TransactionOptions : System.IEquatable { - private int _dummyPrimitive; + private readonly int _dummyPrimitive; public System.Transactions.IsolationLevel IsolationLevel { get { throw null; } set { } } public System.TimeSpan Timeout { get { throw null; } set { } } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } + public bool Equals(System.Transactions.TransactionOptions other) { throw null; } public override int GetHashCode() { throw null; } public static bool operator ==(System.Transactions.TransactionOptions x, System.Transactions.TransactionOptions y) { throw null; } public static bool operator !=(System.Transactions.TransactionOptions x, System.Transactions.TransactionOptions y) { throw null; } diff --git a/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionOptions.cs b/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionOptions.cs index 1fa34283bb455..4ce7bb4bd1394 100644 --- a/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionOptions.cs +++ b/src/libraries/System.Transactions.Local/src/System/Transactions/TransactionOptions.cs @@ -5,7 +5,7 @@ namespace System.Transactions { - public struct TransactionOptions + public struct TransactionOptions : IEquatable { private TimeSpan _timeout; private IsolationLevel _isolationLevel; @@ -26,7 +26,10 @@ public IsolationLevel IsolationLevel public override bool Equals([NotNullWhen(true)] object? obj) => obj is TransactionOptions transactionOptions && Equals(transactionOptions); - private bool Equals(TransactionOptions other) => + /// Indicates whether the current instance is equal to another instance of the same type. + /// An instance to compare with this instance. + /// true if the current instance is equal to the other instance; otherwise, false. + public bool Equals(TransactionOptions other) => _timeout == other._timeout && _isolationLevel == other._isolationLevel; diff --git a/src/mono/System.Private.CoreLib/src/Mono/RuntimeHandles.cs b/src/mono/System.Private.CoreLib/src/Mono/RuntimeHandles.cs index c62dde6612049..90b612313c19d 100644 --- a/src/mono/System.Private.CoreLib/src/Mono/RuntimeHandles.cs +++ b/src/mono/System.Private.CoreLib/src/Mono/RuntimeHandles.cs @@ -7,7 +7,7 @@ namespace Mono { - internal unsafe struct RuntimeClassHandle + internal unsafe struct RuntimeClassHandle : IEquatable { private readonly RuntimeStructs.MonoClass* value; @@ -125,7 +125,7 @@ private int GetConstraintsCount() } } - internal struct RuntimeEventHandle + internal struct RuntimeEventHandle : IEquatable { private readonly IntPtr value; @@ -165,7 +165,7 @@ public override int GetHashCode() } } - internal struct RuntimePropertyHandle + internal struct RuntimePropertyHandle : IEquatable { private readonly IntPtr value; diff --git a/src/mono/System.Private.CoreLib/src/System/ModuleHandle.cs b/src/mono/System.Private.CoreLib/src/System/ModuleHandle.cs index 9f73b99fb6db9..c30bf25582a3a 100644 --- a/src/mono/System.Private.CoreLib/src/System/ModuleHandle.cs +++ b/src/mono/System.Private.CoreLib/src/System/ModuleHandle.cs @@ -6,7 +6,7 @@ namespace System { - public struct ModuleHandle + public struct ModuleHandle : IEquatable { private readonly IntPtr value; diff --git a/src/mono/System.Private.CoreLib/src/System/Nullable.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Nullable.Mono.cs index 23f7668e73549..c120455199922 100644 --- a/src/mono/System.Private.CoreLib/src/System/Nullable.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Nullable.Mono.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#pragma warning disable CA1066 // Implement IEquatable when overriding Object.Equals + namespace System { public partial struct Nullable diff --git a/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs b/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs index af1cead1c9593..9b9c5a410cf2f 100644 --- a/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs +++ b/src/mono/wasm/debugger/BrowserDebugProxy/DevToolsHelper.cs @@ -14,7 +14,7 @@ namespace Microsoft.WebAssembly.Diagnostics { - public struct SessionId + public struct SessionId : IEquatable { public readonly string sessionId; @@ -26,7 +26,9 @@ public SessionId(string sessionId) // hashset treats 0 as unset public override int GetHashCode() => sessionId?.GetHashCode() ?? -1; - public override bool Equals(object obj) => (obj is SessionId) ? ((SessionId)obj).sessionId == sessionId : false; + public override bool Equals(object obj) => obj is SessionId other && Equals(other); + + public bool Equals(SessionId other) => other.sessionId == sessionId; public static bool operator ==(SessionId a, SessionId b) => a.sessionId == b.sessionId; @@ -37,7 +39,7 @@ public SessionId(string sessionId) public override string ToString() => $"session-{sessionId}"; } - public struct MessageId + public struct MessageId : IEquatable { public readonly string sessionId; public readonly int id; @@ -54,7 +56,9 @@ public MessageId(string sessionId, int id) public override int GetHashCode() => (sessionId?.GetHashCode() ?? 0) ^ id.GetHashCode(); - public override bool Equals(object obj) => (obj is MessageId) ? ((MessageId)obj).sessionId == sessionId && ((MessageId)obj).id == id : false; + public override bool Equals(object obj) => obj is MessageId other && Equals(other); + + public bool Equals(MessageId other) => other.sessionId == sessionId && other.id == id; } internal class DotnetObjectId diff --git a/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs b/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs index 9526a602876f2..34b42e2db3ad6 100644 --- a/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs +++ b/src/tasks/WasmAppBuilder/PInvokeTableGenerator.cs @@ -478,7 +478,9 @@ private static bool IsBlittable (Type type) private static void Error (string msg) => throw new LogAsErrorException(msg); } +#pragma warning disable CA1067 internal sealed class PInvoke : IEquatable +#pragma warning restore CA1067 { public PInvoke(string entryPoint, string module, MethodInfo method) {