Modify S4050: Promote C# rule to SonarWay (#4135)

This commit is contained in:
Sebastien Marichal 2024-08-09 16:46:04 +02:00 committed by GitHub
parent 78f32ca6fe
commit dce07c6f35
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 52 additions and 51 deletions

View File

@ -28,7 +28,7 @@
"sqKey": "S4050", "sqKey": "S4050",
"scope": "All", "scope": "All",
"defaultQualityProfiles": [ "defaultQualityProfiles": [
"Sonar way"
], ],
"quickfix": "unknown" "quickfix": "unknown"
} }

View File

@ -1,59 +1,54 @@
== Why is this an issue? == Why is this an issue?
When implementing operator overloads, it is very important to make sure that all related operators and methods are consistent in their implementation. When overloading some arithmetic operator overloads, it is very important to make sure that all related operators and methods are consistent in their implementation.
The following guidelines should be followed: The following guidelines should be followed:
* When providing ``++operator ==++`` you should also provide ``++operator !=++`` and vice-versa. * When providing `operator ==, !=` you should also provide `Equals(Object)` and `GetHashCode()`.
* When providing ``++operator ==++`` you should also provide ``++Equals(Object)++`` and ``++GetHashCode()++``. * When providing `operator +, -, *, / or %` you should also provide `operator ==`, respecting the previous guideline.
* When providing ``++operator +, -, *, / or %++`` you should also provide ``++operator ==++``, respecting previous guidelines.
This rule raises an issue when any of these guidelines are not followed on publicly-visible type (public, protected or protected internal). This rule raises an issue when any of these guidelines are not followed on a publicly-visible class or struct (`public`, `protected` or `protected internal`).
== How to fix it
=== Noncompliant code example Make sure to implement all related operators.
[source,csharp] === Code examples
==== Noncompliant code example
[source,csharp,diff-id=1,diff-type=noncompliant]
---- ----
using System; public class Foo // Noncompliant
namespace MyLibrary
{ {
public class Foo // Noncompliant
{
private int left; private int left;
private int right; private int right;
public Foo(int l, int r) public Foo(int l, int r)
{ {
this.left = l; this.left = l;
this.right = r; this.right = r;
} }
public static Foo operator +(Foo a, Foo b) public static Foo operator +(Foo a, Foo b)
{ {
return new Foo(a.left + b.left, a.right + b.right); return new Foo(a.left + b.left, a.right + b.right);
} }
public static Foo operator -(Foo a, Foo b) public static Foo operator -(Foo a, Foo b)
{ {
return new Foo(a.left - b.left, a.right - b.right); return new Foo(a.left - b.left, a.right - b.right);
} }
}
} }
---- ----
=== Compliant solution ==== Compliant solution
[source,csharp] [source,csharp,diff-id=1,diff-type=compliant]
---- ----
using System; public class Foo
namespace MyLibrary
{ {
public class Foo
{
private int left; private int left;
private int right; private int right;
@ -63,42 +58,48 @@ namespace MyLibrary
this.right = r; this.right = r;
} }
public static Foo operator +(Foo a, Foo b)
{
return new Foo(a.left + b.left, a.right + b.right);
}
public static Foo operator -(Foo a, Foo b)
{
return new Foo(a.left - b.left, a.right - b.right);
}
public static bool operator ==(Foo a, Foo b)
{
return (a.left == b.left && a.right == b.right);
}
public static bool operator !=(Foo a, Foo b)
{
return !(a == b);
}
public override bool Equals(Object obj) public override bool Equals(Object obj)
{ {
Foo a = obj as Foo; var a = obj as Foo;
if (a == null) if (a == null)
return false; return false;
return this == a; return this == a;
} }
public override int GetHashCode() public override int GetHashCode()
{ {
return (this.left * 10) + this.right; return HashCode.Combine(right, left);
}
public static Foo operator +(Foo a, Foo b)
{
return new Foo(a.left + b.left, a.right + b.right);
}
public static Foo operator -(Foo a, Foo b)
{
return new Foo(a.left - b.left, a.right - b.right);
}
public static bool operator ==(Foo a, Foo b)
{
return a.left == b.left && a.right == b.right;
}
public static bool operator !=(Foo a, Foo b)
{
return !(a == b);
} }
}
} }
---- ----
== Resources
=== Documentation
* Microsoft Learn - https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/operator-overloading[Operator overloading]
* Microsoft Learn - https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/equality-operators[Equality operators]
* Microsoft Learn - https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/arithmetic-operators[Arithmetic operators (C# reference)]
ifdef::env-github,rspecator-view[] ifdef::env-github,rspecator-view[]
''' '''