rspec/rules/S3610/csharp/rule.adoc
Marco Borgeaud cd424756a0
Validate asciidoc ifdef/endif (#3311)
Fix kotlin:S6511
2023-10-18 09:43:40 +00:00

107 lines
4.1 KiB
Plaintext

== Why is this an issue?
Calling https://learn.microsoft.com/en-us/dotnet/api/system.object.gettype[GetType()] on a https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/nullable-value-types[nullable value type] object returns the underlying value type. Therefore, comparing the returned https://learn.microsoft.com/en-us/dotnet/api/system.type[`Type`] object to `typeof(Nullable<SomeType>)` will either throw an https://learn.microsoft.com/en-us/dotnet/api/system.nullreferenceexception[NullReferenceException] or the result will always be `true` or `false` and can be known at compile time.
== How to fix it
=== Code examples
==== Noncompliant code example
[source,csharp,diff-id=1,diff-type=noncompliant]
----
void DoChecks<T>(Nullable<T> value) where T : struct
{
bool areEqual = value.GetType() == typeof(Nullable<int>); // Noncompliant: always false
bool areNotEqual = value.GetType() != typeof(Nullable<int>); // Noncompliant: always true
Nullable<int> nullable = null;
bool nullComparison = nullable.GetType() != typeof(Nullable<int>); // Noncompliant: throws NullReferenceException
}
----
==== Compliant solution
[source,csharp,diff-id=1,diff-type=compliant]
----
void DoChecks<T>(Nullable<T> value) where T : struct
{
bool areEqual = value.GetType() == typeof(int); // Compliant: can be true or false
bool areNotEqual = value.GetType() != typeof(int); // Compliant: can be true or false
Nullable<int> nullable = null;
bool nullComparison = nullable is not null && nullable.GetType() == typeof(int); // Compliant: does not throw NullReferenceException
}
----
== Resources
=== Documentation
* Microsoft Learn - https://learn.microsoft.com/en-us/dotnet/api/system.object.gettype[Object.GetType Method]
* Microsoft Learn - https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/nullable-value-types[Nullable value types (C# reference)]
* Microsoft Learn - https://learn.microsoft.com/en-us/dotnet/api/system.type[Type Class]
* Microsoft Learn - https://learn.microsoft.com/en-us/dotnet/api/system.nullreferenceexception[NullReferenceException Class]
ifdef::env-github,rspecator-view[]
'''
== Implementation Specification
(visible only on this page)
=== Message
Remove this redundant type comparison.
=== Highlighting
full expression
'''
== Comments And Links
(visible only on this page)
=== relates to: S2219
=== on 25 Apr 2016, 10:24:59 Tamas Vajk wrote:
\[~ann.campbell.2], could you review this RSPEC? Thanks.
=== on 26 Apr 2016, 17:40:16 Ann Campbell wrote:
\[~tamas.vajk] this rule is a subset of what would be covered by an implementation of RSPEC-2583. When reading it my first thought was that you wrote it stand-alone to cover a R# rule, but there are no references...?
Also, if we retain this RSpec, IMO you should add a compliant solution. From the description and code sample, I'm _guessing_ compliance is a straightforward code change...?
=== on 27 Apr 2016, 08:41:57 Tamas Vajk wrote:
\[~ann.campbell.2] yes, it's a special case of RSPEC-2583.
No, it's not a R# rule. It's the outcome of a bug in one of our rules (RSPEC-2219, added an exception there).
The compliant solution is not straightforward. We can't simply replace the comparison with ``++true++`` or ``++false++`` because that was definitely not what was meant. We could change the ``++typeof(Nullable<int>)++`` to ``++typeof(int)++``, but I don't think that covers the user intent. Most probably the user wanted to check if ``++nullable++`` is a ``++Nullable<T>++`` or not, but that's not possible with ``++GetType++``. And there's no straightforward way to do it, unless you have the type of ``++nullable++`` at compile time.
=== on 27 Apr 2016, 17:44:22 Ann Campbell wrote:
\[~tamas.vajk] I had assumed you'd want to use ``++is++`` (or something similar) instead. Glad I didn't fill in a compliant solution! :-)
For me, the description moves very quickly from
____
Calling GetType() on a nullable object returns the underlying value type.
____
to
____
Thus, comparing the returned Type object to typeof(Nullable<SomeType>) doesn't make sense.
____
But if C#ers will understand, I'm good with it.
endif::env-github,rspecator-view[]