Skip to content

Commit f6dd2dc

Browse files
Update RSPEC before 9.27 release (#9419)
1 parent 2508462 commit f6dd2dc

File tree

12 files changed

+152
-111
lines changed

12 files changed

+152
-111
lines changed

analyzers/rspec/cs/S1244.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ <h4>Noncompliant code example</h4>
2020
<pre data-diff-id="1" data-diff-type="noncompliant">
2121
float myNumber = 3.146f;
2222

23-
if (myNumber == 3.146f) //Noncompliant: due to floating point imprecision, this will likely be false
23+
if (myNumber == 3.146f) // Noncompliant: due to floating point imprecision, this will likely be false
2424
{
2525
// ...
2626
}

analyzers/rspec/cs/S1694.html

+71-18
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,31 @@
1+
<p>A <code>class</code> with only <code>abstract</code> methods and no inheritable behavior should be converted to an <a
2+
href="https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/interfaces/"><code>interface</code></a>.</p>
13
<h2>Why is this an issue?</h2>
2-
<p>The purpose of an abstract class is to provide some heritable behaviors while also defining methods which must be implemented by sub-classes.</p>
3-
<p>A <code>class</code> with only <code>abstract</code> methods and no inheritable behavior should be converted to an <code>interface</code>.</p>
4-
<h3>Noncompliant code example</h3>
4+
<p>The purpose of an <a
5+
href="https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/abstract-and-sealed-classes-and-class-members"><code>abstract</code>
6+
class</a> is to provide some overridable behaviors while also defining methods that are required to be implemented by sub-classes.</p>
7+
<p>A class that contains only <code>abstract</code> methods, often called pure abstract class, is effectively an interface, but with the disadvantage
8+
of not being able to be implemented by multiple classes.</p>
9+
<p>Using interfaces over pure abstract classes presents multiple advantages:</p>
10+
<ul>
11+
<li> <a href="https://en.wikipedia.org/wiki/Multiple_inheritance"><strong>Multiple Inheritance</strong></a>: Unlike classes, an interface doesn’t
12+
count towards the single inheritance limit in C#. This means a class can implement multiple interfaces, which can be useful when you need to define
13+
behavior that can be shared across multiple classes. </li>
14+
<li> <a href="https://en.wikipedia.org/wiki/Loose_coupling#In_programming"><strong>Loose Coupling</strong></a>: Interfaces provide a way to achieve
15+
loose coupling between classes. This is because an interface only specifies what methods a class must have, but not how they are implemented. This
16+
makes it easier to swap out implementations without changing the code that uses them. </li>
17+
<li> <a href="https://en.wikipedia.org/wiki/Polymorphism_(computer_science)"><strong>Polymorphism</strong></a>: Interfaces allow you to use
18+
polymorphism, which means you can use an interface type to refer to any object that implements that interface. This can be useful when you want to
19+
write code that can work with any class that implements a certain interface, <em>without knowing what the actual class is</em>. </li>
20+
<li> <a href="https://en.wikipedia.org/wiki/Design_by_contract"><strong>Design by contract</strong></a>: Interfaces provide a clear contract of what
21+
a class should do, without specifying how it should do it. This makes it easier to understand the intended behavior of a class, and to ensure that
22+
different implementations of an interface are consistent with each other. </li>
23+
</ul>
24+
<h3>Exceptions</h3>
25+
<p><code>abstract</code> classes that contain non-abstract methods, in addition to <code>abstract</code> ones, cannot easily be converted to
26+
interfaces, and are not the subject of this rule:</p>
527
<pre>
6-
public abstract class Animal // Noncompliant; should be an interface
7-
{
8-
abstract void Move();
9-
abstract void Feed();
10-
}
11-
</pre>
12-
<h3>Compliant solution</h3>
13-
<pre>
14-
public interface Animal
15-
{
16-
void Move();
17-
void Feed();
18-
}
19-
20-
public abstract class Lamp
28+
public abstract class Lamp // Compliant: Glow is abstract, but FlipSwitch is not
2129
{
2230
private bool switchLamp = false;
2331

@@ -33,4 +41,49 @@ <h3>Compliant solution</h3>
3341
}
3442
}
3543
</pre>
44+
<p>Notice that, since C# 8.0, you can also define <a
45+
href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-8.0/default-interface-methods">default implementations for
46+
interface methods</a>, which is yet another reason to prefer interfaces over abstract classes when you don’t need to provide any inheritable
47+
behavior.</p>
48+
<p>However, interfaces cannot have fields (such as <code>switchLamp</code> in the example above), and that remains true even in C# 8.0 and upwards.
49+
This can be a valid reason to still prefer an abstract class over an interface.</p>
50+
<h2>How to fix it</h2>
51+
<p>Convert the <code>abstract</code> class to an <code>interface</code> with the same methods.</p>
52+
<h3>Code examples</h3>
53+
<h4>Noncompliant code example</h4>
54+
<pre data-diff-id="1" data-diff-type="noncompliant">
55+
public abstract class Animal // Noncompliant: should be an interface
56+
{
57+
public abstract void Move();
58+
public abstract void Feed();
59+
}
60+
</pre>
61+
<h3>Compliant solution</h3>
62+
<pre data-diff-id="1" data-diff-type="compliant">
63+
public interface Animal
64+
{
65+
void Move();
66+
void Feed();
67+
}
68+
</pre>
69+
<h2>Resources</h2>
70+
<h3>Documentation</h3>
71+
<ul>
72+
<li> Microsoft Learn - <a
73+
href="https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/abstract-and-sealed-classes-and-class-members">Abstract
74+
and Sealed Classes and Class Members (C# Programming Guide)</a> </li>
75+
<li> Microsoft Learn - <a href="https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/interfaces/">Interfaces - define behavior for
76+
multiple types</a> </li>
77+
<li> Microsoft Learn - <a href="https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/interfaces/default-interface-methods">Default
78+
Interface Methods</a> </li>
79+
<li> Microsoft Learn - <a
80+
href="https://learn.microsoft.com/en-us/dotnet/csharp/advanced-topics/interface-implementation/default-interface-methods-versions">Tutorial: Update
81+
interfaces with default interface methods</a> </li>
82+
<li> Microsoft Learn - <a href="https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/object-oriented/inheritance">Inheritance - derive types
83+
to create more specialized behavior</a> </li>
84+
<li> Wikipedia - <a href="https://en.wikipedia.org/wiki/Multiple_inheritance">Multiple Inheritance</a> </li>
85+
<li> Wikipedia - <a href="https://en.wikipedia.org/wiki/Loose_coupling#In_programming">Loose Coupling - In programming</a> </li>
86+
<li> Wikipedia - <a href="https://en.wikipedia.org/wiki/Polymorphism_(computer_science)">Polymorphism (computer science)</a> </li>
87+
<li> Wikipedia - <a href="https://en.wikipedia.org/wiki/Design_by_contract">Design by contract</a> </li>
88+
</ul>
3689

analyzers/rspec/cs/S2094.html

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ <h3>Compliant solution</h3>
1717
<h3>Exceptions</h3>
1818
<ul>
1919
<li> Partial classes are ignored entirely, as source generators often use them. </li>
20-
<li> Classes with names ending in <code>Command</code>, <code>Message</code>, or <code>Event</code> are ignored as messaging libraries often use
21-
them. </li>
20+
<li> Classes with names ending in <code>Command</code>, <code>Message</code>, <code>Event</code>, or <code>Query</code> are ignored as messaging
21+
libraries often use them. </li>
2222
<li> Subclasses of <code>System.Exception</code> are ignored; even an empty Exception class can provide helpful information by its type name alone.
2323
</li>
2424
<li> Subclasses of <code>System.Attribute</code> and classes annotated with attributes are ignored. </li>

analyzers/rspec/cs/S3254.html

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ <h3>Noncompliant code example</h3>
55
public void M(int x, int y=5, int z = 7) { /* ... */ }
66

77
// ...
8-
M(1, 5); //Noncompliant, y has the default value
9-
M(1, z: 7); //Noncompliant, z has the default value
8+
M(1, 5); // Noncompliant, y has the default value
9+
M(1, z: 7); // Noncompliant, z has the default value
1010
</pre>
1111
<h3>Compliant solution</h3>
1212
<pre>

analyzers/rspec/cs/S3264.html

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ <h3>Noncompliant code example</h3>
44
<pre>
55
class UninvokedEventSample
66
{
7-
private event Action&lt;object, EventArgs&gt; Happened; //Noncompliant
7+
private event Action&lt;object, EventArgs&gt; Happened; // Noncompliant
88

99
public void RegisterEventHandler(Action&lt;object, EventArgs&gt; handler)
1010
{
11-
Happened += handler; //we register some event handlers
11+
Happened += handler; // we register some event handlers
1212
}
1313

1414
public void RaiseEvent()

analyzers/rspec/cs/S5344.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ <h4>Compliant solution</h4>
135135
RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider();
136136
byte[] salt = new byte[32];
137137
rngCsp.GetBytes(salt);
138-
Rfc2898DeriveBytes kdf = new Rfc2898DeriveBytes(password, salt, 100_000, HashAlgorithmName.SHA256); // Noncompliant
138+
Rfc2898DeriveBytes kdf = new Rfc2898DeriveBytes(password, salt, 100_000, HashAlgorithmName.SHA256); // Compliant
139139
string hashed = Convert.ToBase64String(kdf.GetBytes(256 / 8));
140140
</pre>
141141
<h3>How does this work?</h3>

analyzers/rspec/cs/S6962.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ <h4>Noncompliant code example</h4>
3939
[HttpGet]
4040
public async Task&lt;string&gt; Foo()
4141
{
42-
using var client = new HttpClient(); //Noncompliant
42+
using var client = new HttpClient(); // Noncompliant
4343
return await client.GetStringAsync(_url);
4444
}
4545
}

analyzers/rspec/cs/S6962.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
"func": "Constant\/Issue",
77
"constantCost": "1h"
88
},
9-
"tags": [],
9+
"tags": [
10+
"asp.net"
11+
],
1012
"defaultSeverity": "Major",
1113
"ruleSpecification": "RSPEC-6962",
1214
"sqKey": "S6962",

analyzers/rspec/vbnet/S2094.html

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ <h3>Compliant solution</h3>
1717
<h3>Exceptions</h3>
1818
<ul>
1919
<li> Partial classes are ignored entirely, as source generators often use them. </li>
20-
<li> Classes with names ending in <code>Command</code>, <code>Message</code>, or <code>Event</code> are ignored as messaging libraries often use
21-
them. </li>
20+
<li> Classes with names ending in <code>Command</code>, <code>Message</code>, <code>Event</code>, or <code>Query</code> are ignored as messaging
21+
libraries often use them. </li>
2222
<li> Subclasses of <code>System.Exception</code> are ignored; even an empty Exception class can provide helpful information by its type name alone.
2323
</li>
2424
<li> Subclasses of <code>System.Attribute</code> and classes annotated with attributes are ignored. </li>

0 commit comments

Comments
 (0)