Runtime: ConsoleKeyInfo does not implement IEquatable

Created on 24 Jan 2020  路  10Comments  路  Source: dotnet/runtime

System.ConsoleKeyInfo does not implement System.IEquatable<System.ConsoleKeyInfo>. Is this intended?

api-approved area-System.Console

Most helpful comment

Well, I think the question is that ConsoleKeyInfo already has all of the implementation to satisfy implementing the IEquatable<ConsoleKeyInfo> interface. It already has bool Equals(ConsoleKeyInfo) implemented.

https://github.com/dotnet/runtime/blob/cb1fc80f020c87a8720ea895e203c1f14cb456b8/src/libraries/System.Console/src/System/ConsoleKeyInfo.cs#L55-L58

I think then this is an API proposal:

 namespace System
 {
-    public readonly struct ConsoleKeyInfo
+    public readonly struct ConsoleKeyInfo : IEquatable<ConsoleKeyInfo>
     {

All 10 comments

What are you trying to achieve?

Well, I think the question is that ConsoleKeyInfo already has all of the implementation to satisfy implementing the IEquatable<ConsoleKeyInfo> interface. It already has bool Equals(ConsoleKeyInfo) implemented.

https://github.com/dotnet/runtime/blob/cb1fc80f020c87a8720ea895e203c1f14cb456b8/src/libraries/System.Console/src/System/ConsoleKeyInfo.cs#L55-L58

I think then this is an API proposal:

 namespace System
 {
-    public readonly struct ConsoleKeyInfo
+    public readonly struct ConsoleKeyInfo : IEquatable<ConsoleKeyInfo>
     {

What are you trying to achieve?

A common scenario could be implementing a TUI and maintaining a dictionary of ConsoleKeyInfos to hotkey handlers (think of tmux or emacs or anything that allows programmable hotkeys). It is possible to use an equality comparer lambda, but it would be nicer for ConsoleKeyInfo to already implement IEquatable.

@terrajobst ConsoleKeyInfo implements Equals(object), Equals(ConsoleKeyInfo) and overrides GetHashCode but does not implement the IEquatable<ConsoleKeyInfo> interface. Do I need an API review for:

-public readonly struct ConsoleKeyInfo
+public readonly struct ConsoleKeyInfo : IEquatable<ConsoleKeyInfo>

@jeffhandley it looks like a good candidate for an analyzer (#31996 is another example)

@adamsitnik Yeah that seems like a cool analyzer idea. Feel free to submit an issue for that and tag it with code-analyzer.

Do I need an API review for

Yes..hopefully quick and easy one though

it looks like a good candidate for an analyzer

It actually already exists: CA1066
https://docs.microsoft.com/en-us/visualstudio/code-quality/ca1066?view=vs-2019

It actually already exists: CA1066

@stephentoub thanks, I did not know about it!

Is there any reason why it's disabled in this repo?

https://github.com/dotnet/runtime/blob/3c9fcce29d00d0d38148c4113b17aeeaa5cbc970/eng/CodeAnalysis.ruleset#L54

Is there any reason why it's disabled in this repo?

Most if not all of the API-focused rules are disabled because they're not actionable on their own: we have a dedicated API review process for any new public APIs, so a developer can't just go in and fix a violation on their own. There are currently dozens of warnings from the rule on public surface area, mostly APIs that have been around for a very long time. If someone did the work to catalogue all of the public APIs that would need to be augmented, run them all through API review, and get all the APIs added, then we could enable the rule, assuming we wanted to enforce it in all public APIs shipped from this repo moving forward.

For reference, when I build locally, these are the warnings I get from it:

D:\repos\runtime\src\libraries\System.Private.CoreLib\src\System\Nullable.cs(17,27): warning CA1066: Type System.Nullable<T> should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\coreclr\src\System.Private.CoreLib\System.Private.CoreLib.csproj]
D:\repos\runtime\src\libraries\System.Private.CoreLib\src\System\HashCode.cs(54,19): warning CA1066: Type System.HashCode should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\coreclr\src\System.Private.CoreLib\System.Private.CoreLib.csproj]
src\System\Runtime\InteropServices\GCHandle.CoreCLR.cs(12,27): warning CA1066: Type System.Runtime.InteropServices.GCHandle should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\coreclr\src\System.Private.CoreLib\System.Private.CoreLib.csproj]
D:\repos\runtime\src\libraries\System.Private.CoreLib\src\System\ArraySegment.cs(29,28): warning CA1066: Type System.ArraySegment<T> should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\coreclr\src\System.Private.CoreLib\System.Private.CoreLib.csproj]
D:\repos\runtime\src\libraries\System.Private.CoreLib\src\System\Runtime\Serialization\StreamingContext.cs(7,28): warning CA1066: Type System.Runtime.Serialization.StreamingContext should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\coreclr\src\System.Private.CoreLib\System.Private.CoreLib.csproj]
src\System\RuntimeHandles.cs(16,26): warning CA1066: Type System.RuntimeTypeHandle should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\coreclr\src\System.Private.CoreLib\System.Private.CoreLib.csproj]
src\System\RuntimeHandles.cs(690,26): warning CA1066: Type System.RuntimeMethodHandle should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\coreclr\src\System.Private.CoreLib\System.Private.CoreLib.csproj]
src\System\RuntimeHandles.cs(1014,26): warning CA1066: Type System.RuntimeFieldHandle should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\coreclr\src\System.Private.CoreLib\System.Private.CoreLib.csproj]
src\System\RuntimeHandles.cs(1121,26): warning CA1066: Type System.ModuleHandle should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\coreclr\src\System.Private.CoreLib\System.Private.CoreLib.csproj]
D:\repos\runtime\src\libraries\System.Private.CoreLib\src\System\Runtime\InteropServices\ArrayWithOffset.cs(9,19): warning CA1066: Type System.Runtime.InteropServices.ArrayWithOffset should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\coreclr\src\System.Private.CoreLib\System.Private.CoreLib.csproj]
D:\repos\runtime\src\libraries\System.Private.CoreLib\src\System\Diagnostics\Tracing\EventDescriptor.cs(21,21): warning CA1066: Type System.Diagnostics.Tracing.EventDescriptor should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\coreclr\src\System.Private.CoreLib\System.Private.CoreLib.csproj]
src\System\Diagnostics\SymbolStore\Token.cs(15,21): warning CA1066: Type System.Diagnostics.SymbolStore.SymbolToken should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\coreclr\src\System.Private.CoreLib\System.Private.CoreLib.csproj]
src\System\Reflection\MdImport.cs(198,30): warning CA1066: Type System.Reflection.MetadataImport should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\coreclr\src\System.Private.CoreLib\System.Private.CoreLib.csproj]
src\System\Reflection\CustomAttribute.cs(501,36): warning CA1066: Type System.Reflection.CustomAttributeTypedArgument should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\coreclr\src\System.Private.CoreLib\System.Private.CoreLib.csproj]
D:\repos\runtime\src\libraries\System.Private.CoreLib\src\System\Reflection\CustomAttributeNamedArgument.cs(7,36): warning CA1066: Type System.Reflection.CustomAttributeNamedArgument should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\coreclr\src\System.Private.CoreLib\System.Private.CoreLib.csproj]
D:\repos\runtime\src\libraries\System.Private.CoreLib\src\System\Threading\CancellationToken.cs(31,28): warning CA1066: Type System.Threading.CancellationToken should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\coreclr\src\System.Private.CoreLib\System.Private.CoreLib.csproj]
D:\repos\runtime\src\libraries\System.Private.CoreLib\src\System\Threading\ExecutionContext.cs(575,19): warning CA1066: Type System.Threading.AsyncFlowControl should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\coreclr\src\System.Private.CoreLib\System.Private.CoreLib.csproj]
D:\repos\runtime\src\libraries\System.Private.CoreLib\src\System\Reflection\Emit\EventToken.cs(7,19): warning CA1066: Type System.Reflection.Emit.EventToken should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\coreclr\src\System.Private.CoreLib\System.Private.CoreLib.csproj]
D:\repos\runtime\src\libraries\System.Private.CoreLib\src\System\Reflection\Emit\FieldToken.cs(13,19): warning CA1066: Type System.Reflection.Emit.FieldToken should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\coreclr\src\System.Private.CoreLib\System.Private.CoreLib.csproj]
D:\repos\runtime\src\libraries\System.Private.CoreLib\src\System\Reflection\Emit\MethodToken.cs(7,19): warning CA1066: Type System.Reflection.Emit.MethodToken should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\coreclr\src\System.Private.CoreLib\System.Private.CoreLib.csproj]
D:\repos\runtime\src\libraries\System.Private.CoreLib\src\System\Reflection\Emit\ParameterToken.cs(11,19): warning CA1066: Type System.Reflection.Emit.ParameterToken should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\coreclr\src\System.Private.CoreLib\System.Private.CoreLib.csproj]
D:\repos\runtime\src\libraries\System.Private.CoreLib\src\System\Reflection\Emit\PropertyToken.cs(7,19): warning CA1066: Type System.Reflection.Emit.PropertyToken should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\coreclr\src\System.Private.CoreLib\System.Private.CoreLib.csproj]
D:\repos\runtime\src\libraries\System.Private.CoreLib\src\System\Reflection\Emit\SignatureToken.cs(7,19): warning CA1066: Type System.Reflection.Emit.SignatureToken should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\coreclr\src\System.Private.CoreLib\System.Private.CoreLib.csproj]
D:\repos\runtime\src\libraries\System.Private.CoreLib\src\System\Reflection\Emit\StringToken.cs(7,19): warning CA1066: Type System.Reflection.Emit.StringToken should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\coreclr\src\System.Private.CoreLib\System.Private.CoreLib.csproj]
D:\repos\runtime\src\libraries\System.Private.CoreLib\src\System\Reflection\Emit\TypeToken.cs(7,19): warning CA1066: Type System.Reflection.Emit.TypeToken should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\coreclr\src\System.Private.CoreLib\System.Private.CoreLib.csproj]
Dependency.cs(10,19): warning CA1066: Type Microsoft.Extensions.DependencyModel.Dependency should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\Microsoft.Extensions.DependencyModel\src\Microsoft.Extensions.DependencyModel.csproj]
EventId.cs(10,28): warning CA1066: Type Microsoft.Extensions.Logging.EventId should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\Microsoft.Extensions.Logging.Abstractions\src\Microsoft.Extensions.Logging.Abstractions.csproj]
System\Collections\Specialized\BitVector32.cs(14,19): warning CA1066: Type System.Collections.Specialized.BitVector32 should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\System.Collections.Specialized\src\System.Collections.Specialized.csproj]
System\Collections\Specialized\BitVector32.cs(230,32): warning CA1066: Type System.Collections.Specialized.BitVector32.Section should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\System.Collections.Specialized\src\System.Collections.Specialized.csproj]
System\Collections\Immutable\ImmutableDictionary_2.HashBucket.cs(19,34): warning CA1066: Type System.Collections.Immutable.ImmutableDictionary<TKey, TValue>.HashBucket should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\System.Collections.Immutable\src\System.Collections.Immutable.csproj]
System\Collections\Immutable\ImmutableHashSet_1.HashBucket.cs(34,34): warning CA1066: Type System.Collections.Immutable.ImmutableHashSet<T>.HashBucket should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\System.Collections.Immutable\src\System.Collections.Immutable.csproj]
System\ComponentModel\Composition\ReflectionModel\LazyMemberInfo.cs(12,19): warning CA1066: Type System.ComponentModel.Composition.ReflectionModel.LazyMemberInfo should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\System.ComponentModel.Composition\src\System.ComponentModel.Composition.csproj]
System\ConsoleKeyInfo.cs(9,28): warning CA1066: Type System.ConsoleKeyInfo should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\System.Console\src\System.Console.csproj]
System\Diagnostics\CounterSample.cs(10,28): warning CA1066: Type System.Diagnostics.CounterSample should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\System.Diagnostics.PerformanceCounter\src\System.Diagnostics.PerformanceCounter.csproj]
System\Data\DataKey.cs(9,30): warning CA1066: Type System.Data.DataKey should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\System.Data.Common\src\System.Data.Common.csproj]
System\Data\Selection.cs(12,30): warning CA1066: Type System.Data.IndexField should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\System.Data.Common\src\System.Data.Common.csproj]
System\Data\SQLTypes\SQLDateTime.cs(24,19): warning CA1066: Type System.Data.SqlTypes.SqlDateTime should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\System.Data.Common\src\System.Data.Common.csproj]
System\Data\SQLTypes\SQLDouble.cs(22,19): warning CA1066: Type System.Data.SqlTypes.SqlDouble should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\System.Data.Common\src\System.Data.Common.csproj]
System\Data\SQLTypes\SQLInt16.cs(20,19): warning CA1066: Type System.Data.SqlTypes.SqlInt16 should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\System.Data.Common\src\System.Data.Common.csproj]
System\Data\SQLTypes\SQLDecimal.cs(21,19): warning CA1066: Type System.Data.SqlTypes.SqlDecimal should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\System.Data.Common\src\System.Data.Common.csproj]
System\Data\SQLTypes\SQLInt32.cs(20,19): warning CA1066: Type System.Data.SqlTypes.SqlInt32 should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\System.Data.Common\src\System.Data.Common.csproj]
System\Data\SQLTypes\SQLInt64.cs(21,19): warning CA1066: Type System.Data.SqlTypes.SqlInt64 should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\System.Data.Common\src\System.Data.Common.csproj]
System\Data\SQLTypes\SQLSingle.cs(20,19): warning CA1066: Type System.Data.SqlTypes.SqlSingle should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\System.Data.Common\src\System.Data.Common.csproj]
System\Data\SQLTypes\SQLMoney.cs(24,19): warning CA1066: Type System.Data.SqlTypes.SqlMoney should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\System.Data.Common\src\System.Data.Common.csproj]
System\Data\SQLTypes\SQLString.cs(37,19): warning CA1066: Type System.Data.SqlTypes.SqlString should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\System.Data.Common\src\System.Data.Common.csproj]
System\Data\SQLTypes\SQLBinary.cs(15,19): warning CA1066: Type System.Data.SqlTypes.SqlBinary should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\System.Data.Common\src\System.Data.Common.csproj]
System\Data\SQLTypes\SQLByte.cs(21,19): warning CA1066: Type System.Data.SqlTypes.SqlByte should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\System.Data.Common\src\System.Data.Common.csproj]
System\Data\SQLTypes\SQLGuid.cs(19,19): warning CA1066: Type System.Data.SqlTypes.SqlGuid should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\System.Data.Common\src\System.Data.Common.csproj]
System\Data\SQLTypes\SQLBoolean.cs(21,19): warning CA1066: Type System.Data.SqlTypes.SqlBoolean should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\System.Data.Common\src\System.Data.Common.csproj]
System\ComponentModel\InterlockedBitVector32.cs(14,21): warning CA1066: Type System.ComponentModel.InterlockedBitVector32 should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\System.ComponentModel.TypeConverter\src\System.ComponentModel.TypeConverter.csproj]
System\ComponentModel\Design\Serialization\MemberRelationshipService.cs(150,24): warning CA1066: Type System.ComponentModel.Design.Serialization.MemberRelationshipService.RelationshipEntry should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\System.ComponentModel.TypeConverter\src\System.ComponentModel.TypeConverter.csproj]
System\ComponentModel\Design\Serialization\MemberRelationshipService.cs(188,28): warning CA1066: Type System.ComponentModel.Design.Serialization.MemberRelationship should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\System.ComponentModel.TypeConverter\src\System.ComponentModel.TypeConverter.csproj]
System\Drawing\CharacterRange.cs(11,19): warning CA1066: Type System.Drawing.CharacterRange should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\System.Drawing.Common\src\System.Drawing.Common.csproj]
System\Drawing\Printing\TriState.cs(7,38): warning CA1066: Type System.Drawing.Printing.TriState should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\System.Drawing.Common\src\System.Drawing.Common.csproj]
System\Linq\Expressions\Interpreter\LocalVariables.cs(50,30): warning CA1066: Type System.Linq.Expressions.Interpreter.LocalDefinition should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\System.Linq.Expressions\src\System.Linq.Expressions.csproj]
System\Net\Sockets\IPPacketInformation.cs(7,19): warning CA1066: Type System.Net.Sockets.IPPacketInformation should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\System.Net.Sockets\src\System.Net.Sockets.csproj]
System\Runtime\Caching\CacheExpires.cs(17,21): warning CA1066: Type System.Runtime.Caching.ExpiresEntryRef should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\System.Runtime.Caching\src\System.Runtime.Caching.csproj]
System\Runtime\Caching\CacheUsage.cs(17,21): warning CA1066: Type System.Runtime.Caching.UsageEntryRef should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\System.Runtime.Caching\src\System.Runtime.Caching.csproj]
System\Threading\LockCookie.cs(11,19): warning CA1066: Type System.Threading.LockCookie should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\System.Threading\src\System.Threading.csproj]
System\Xml\BinaryXml\XmlBinaryReader.cs(62,25): warning CA1066: Type System.Xml.XmlSqlBinaryReader.QName should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\System.Private.Xml\src\System.Private.Xml.csproj]
System\Xml\Xsl\Pair.cs(10,21): warning CA1066: Type System.Xml.Xsl.Int32Pair should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\System.Private.Xml\src\System.Private.Xml.csproj]
System\Xml\Xsl\XmlQueryCardinality.cs(14,21): warning CA1066: Type System.Xml.Xsl.XmlQueryCardinality should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\System.Private.Xml\src\System.Private.Xml.csproj]
System\Xml\BinaryXml\XmlBinaryReader.cs(62,25): warning CA1066: Type System.Xml.XmlSqlBinaryReader.QName should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\System.Private.Xml\src\System.Private.Xml.csproj]
System\Xml\Xsl\Pair.cs(10,21): warning CA1066: Type System.Xml.Xsl.Int32Pair should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\System.Private.Xml\src\System.Private.Xml.csproj]
System\Xml\Xsl\XmlQueryCardinality.cs(14,21): warning CA1066: Type System.Xml.Xsl.XmlQueryCardinality should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\System.Private.Xml\src\System.Private.Xml.csproj]
System\ServiceProcess\SessionChangeDescription.cs(7,28): warning CA1066: Type System.ServiceProcess.SessionChangeDescription should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\System.ServiceProcess.ServiceController\src\System.ServiceProcess.ServiceController.csproj]
System\Transactions\TransactionOptions.cs(7,19): warning CA1066: Type System.Transactions.TransactionOptions should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\System.Transactions.Local\src\System.Transactions.Local.csproj]
System\Diagnostics\SymbolStore\SymbolToken.cs(7,28): warning CA1066: Type System.Diagnostics.SymbolStore.SymbolToken should implement IEquatable<T> because it overrides Equals [D:\repos\runtime\src\libraries\System.Diagnostics.StackTrace\src\System.Diagnostics.StackTrace.csproj]

Note that some of these highlight that just because a type overrides Equals doesn't mean it should implement IEquatable. Take Hashcode, for example, which overrides Equals to throw so as to prevent comparison; implementing IEquatable would be a step backwards.

Video

  • Makes sense

C# namespace System { public partial readonly struct ConsoleKeyInfo : IEquatable<ConsoleKeyInfo> { } }

Was this page helpful?
0 / 5 - 0 ratings

Related issues

omajid picture omajid  路  3Comments

EgorBo picture EgorBo  路  3Comments

matty-hall picture matty-hall  路  3Comments

yahorsi picture yahorsi  路  3Comments

jamesqo picture jamesqo  路  3Comments