diff --git a/analyzers/rspec/cs/S1244.html b/analyzers/rspec/cs/S1244.html index 988fa5b667e..ea798821338 100644 --- a/analyzers/rspec/cs/S1244.html +++ b/analyzers/rspec/cs/S1244.html @@ -20,7 +20,7 @@

Noncompliant code example

 float myNumber = 3.146f;
 
-if (myNumber == 3.146f) //Noncompliant: due to floating point imprecision, this will likely be false
+if (myNumber == 3.146f) // Noncompliant: due to floating point imprecision, this will likely be false
 {
   // ...
 }
diff --git a/analyzers/rspec/cs/S1694.html b/analyzers/rspec/cs/S1694.html
index 544f8565a6a..e65e24d82bb 100644
--- a/analyzers/rspec/cs/S1694.html
+++ b/analyzers/rspec/cs/S1694.html
@@ -1,23 +1,31 @@
+

A class with only abstract methods and no inheritable behavior should be converted to an interface.

Why is this an issue?

-

The purpose of an abstract class is to provide some heritable behaviors while also defining methods which must be implemented by sub-classes.

-

A class with only abstract methods and no inheritable behavior should be converted to an interface.

-

Noncompliant code example

+

The purpose of an abstract +class is to provide some overridable behaviors while also defining methods that are required to be implemented by sub-classes.

+

A class that contains only abstract methods, often called pure abstract class, is effectively an interface, but with the disadvantage +of not being able to be implemented by multiple classes.

+

Using interfaces over pure abstract classes presents multiple advantages:

+ +

Exceptions

+

abstract classes that contain non-abstract methods, in addition to abstract ones, cannot easily be converted to +interfaces, and are not the subject of this rule:

-public abstract class Animal // Noncompliant; should be an interface
-{
-  abstract void Move();
-  abstract void Feed();
-}
-
-

Compliant solution

-
-public interface Animal
-{
-  void Move();
-  void Feed();
-}
-
-public abstract class Lamp
+public abstract class Lamp // Compliant: Glow is abstract, but FlipSwitch is not
 {
   private bool switchLamp = false;
 
@@ -33,4 +41,49 @@ 

Compliant solution

} }
+

Notice that, since C# 8.0, you can also define default implementations for +interface methods, which is yet another reason to prefer interfaces over abstract classes when you don’t need to provide any inheritable +behavior.

+

However, interfaces cannot have fields (such as switchLamp in the example above), and that remains true even in C# 8.0 and upwards. +This can be a valid reason to still prefer an abstract class over an interface.

+

How to fix it

+

Convert the abstract class to an interface with the same methods.

+

Code examples

+

Noncompliant code example

+
+public abstract class Animal // Noncompliant: should be an interface
+{
+  public abstract void Move();
+  public abstract void Feed();
+}
+
+

Compliant solution

+
+public interface Animal
+{
+  void Move();
+  void Feed();
+}
+
+

Resources

+

Documentation

+ diff --git a/analyzers/rspec/cs/S2094.html b/analyzers/rspec/cs/S2094.html index 501b08f9462..56d4deca467 100644 --- a/analyzers/rspec/cs/S2094.html +++ b/analyzers/rspec/cs/S2094.html @@ -17,8 +17,8 @@

Compliant solution

Exceptions

Compliant solution

diff --git a/analyzers/rspec/cs/S3264.html b/analyzers/rspec/cs/S3264.html
index 6c9f850a2b2..9a700662311 100644
--- a/analyzers/rspec/cs/S3264.html
+++ b/analyzers/rspec/cs/S3264.html
@@ -4,11 +4,11 @@ 

Noncompliant code example

 class UninvokedEventSample
 {
-    private event Action<object, EventArgs> Happened; //Noncompliant
+    private event Action<object, EventArgs> Happened; // Noncompliant
 
     public void RegisterEventHandler(Action<object, EventArgs> handler)
     {
-        Happened += handler; //we register some event handlers
+        Happened += handler; // we register some event handlers
     }
 
     public void RaiseEvent()
diff --git a/analyzers/rspec/cs/S5344.html b/analyzers/rspec/cs/S5344.html
index 93a8273649c..92f26b5f26a 100644
--- a/analyzers/rspec/cs/S5344.html
+++ b/analyzers/rspec/cs/S5344.html
@@ -135,7 +135,7 @@ 

Compliant solution

RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider(); byte[] salt = new byte[32]; rngCsp.GetBytes(salt); -Rfc2898DeriveBytes kdf = new Rfc2898DeriveBytes(password, salt, 100_000, HashAlgorithmName.SHA256); // Noncompliant +Rfc2898DeriveBytes kdf = new Rfc2898DeriveBytes(password, salt, 100_000, HashAlgorithmName.SHA256); // Compliant string hashed = Convert.ToBase64String(kdf.GetBytes(256 / 8));

How does this work?

diff --git a/analyzers/rspec/cs/S6962.html b/analyzers/rspec/cs/S6962.html index a0c92ad10ce..4dd23b0704a 100644 --- a/analyzers/rspec/cs/S6962.html +++ b/analyzers/rspec/cs/S6962.html @@ -39,7 +39,7 @@

Noncompliant code example

[HttpGet] public async Task<string> Foo() { - using var client = new HttpClient(); //Noncompliant + using var client = new HttpClient(); // Noncompliant return await client.GetStringAsync(_url); } } diff --git a/analyzers/rspec/cs/S6962.json b/analyzers/rspec/cs/S6962.json index 7f75bbd5f10..b9d25981bd2 100644 --- a/analyzers/rspec/cs/S6962.json +++ b/analyzers/rspec/cs/S6962.json @@ -6,7 +6,9 @@ "func": "Constant\/Issue", "constantCost": "1h" }, - "tags": [], + "tags": [ + "asp.net" + ], "defaultSeverity": "Major", "ruleSpecification": "RSPEC-6962", "sqKey": "S6962", diff --git a/analyzers/rspec/vbnet/S2094.html b/analyzers/rspec/vbnet/S2094.html index 236aebc03a8..27f9f629b79 100644 --- a/analyzers/rspec/vbnet/S2094.html +++ b/analyzers/rspec/vbnet/S2094.html @@ -17,8 +17,8 @@

Compliant solution

Exceptions

Hardware configuration:

-BenchmarkDotNet=v0.13.5, OS=Windows 10 (10.0.19045.2846/22H2/2022Update)
+BenchmarkDotNet=v0.13.5, OS=Windows 10 (10.0.19045.4412/22H2/2022Update)
 11th Gen Intel Core i7-11850H 2.50GHz, 1 CPU, 16 logical and 8 physical cores
-.NET SDK=7.0.203
-  [Host]               : .NET 7.0.5 (7.0.523.17405), X64 RyuJIT AVX2
-  .NET 7.0             : .NET 7.0.5 (7.0.523.17405), X64 RyuJIT AVX2
-  .NET Framework 4.6.2 : .NET Framework 4.8.1 (4.8.9139.0), X64 RyuJIT VectorSize=256
+.NET SDK=8.0.301
+  [Host]   : .NET 8.0.6 (8.0.624.26715), X64 RyuJIT AVX2
+  .NET 8.0 : .NET 8.0.6 (8.0.624.26715), X64 RyuJIT AVX2
 
diff --git a/analyzers/src/SonarAnalyzer.CSharp/sonarpedia.json b/analyzers/src/SonarAnalyzer.CSharp/sonarpedia.json index b1751e8bbb0..6df42c584f5 100644 --- a/analyzers/src/SonarAnalyzer.CSharp/sonarpedia.json +++ b/analyzers/src/SonarAnalyzer.CSharp/sonarpedia.json @@ -3,7 +3,7 @@ "languages": [ "CSH" ], - "latest-update": "2024-06-05T08:43:15.694332900Z", + "latest-update": "2024-06-10T14:50:07.301026900Z", "options": { "no-language-in-filenames": true } diff --git a/analyzers/src/SonarAnalyzer.VisualBasic/sonarpedia.json b/analyzers/src/SonarAnalyzer.VisualBasic/sonarpedia.json index 85c38152c2d..6e293fd822d 100644 --- a/analyzers/src/SonarAnalyzer.VisualBasic/sonarpedia.json +++ b/analyzers/src/SonarAnalyzer.VisualBasic/sonarpedia.json @@ -3,7 +3,7 @@ "languages": [ "VBNET" ], - "latest-update": "2024-05-31T08:11:17.885759100Z", + "latest-update": "2024-06-10T14:50:28.179058600Z", "options": { "no-language-in-filenames": true }