Skip to content

Commit c275a36

Browse files
authored
Update ca1036.md (#42739)
1 parent 20759c2 commit c275a36

File tree

8 files changed

+244
-129
lines changed

8 files changed

+244
-129
lines changed

docs/fundamentals/code-analysis/quality-rules/ca1036.md

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ helpviewer_keywords:
1010
- CA1036
1111
author: gewarren
1212
ms.author: gewarren
13+
dev_langs:
14+
- CSharp
15+
- VB
1316
---
1417
# CA1036: Override methods on comparable types
1518

@@ -35,23 +38,42 @@ Types that define a custom sort order implement the <xref:System.IComparable> in
3538

3639
To fix a violation of this rule, override <xref:System.Object.Equals%2A>. If your programming language supports operator overloading, supply the following operators:
3740

38-
- op_Equality
39-
- op_Inequality
40-
- op_LessThan
41-
- op_GreaterThan
42-
43-
In C#, the tokens that are used to represent these operators are as follows:
41+
- `op_Equality`
42+
- `op_Inequality`
43+
- `op_LessThan`
44+
- `op_GreaterThan`
4445

4546
```csharp
46-
==
47-
!=
48-
<
49-
>
47+
// In C#, implement these operators.
48+
public static bool operator ==(SampleClass? one, SampleClass? other) { }
49+
public static bool operator !=(SampleClass? one, SampleClass? other) { }
50+
public static bool operator <(SampleClass? one, SampleClass? other) { }
51+
public static bool operator >(SampleClass? one, SampleClass? other) { }
52+
```
53+
54+
```vb
55+
' In Visual Basic, implement these operators.
56+
57+
Public Shared Operator =(one As SampleClass, other As SampleClass) As Boolean
58+
...
59+
End Operator
60+
61+
Public Shared Operator <>(one As SampleClass, other As SampleClass) As Boolean
62+
...
63+
End Operator
64+
65+
Public Shared Operator <(one As SampleClass, other As SampleClass) As Boolean
66+
...
67+
End Operator
68+
69+
Public Shared Operator >(one As SampleClass, other As SampleClass) As Boolean
70+
...
71+
End Operator
5072
```
5173

5274
## When to suppress warnings
5375

54-
It is safe to suppress a warning from rule CA1036 when the violation is caused by missing operators and your programming language does not support operator overloading, as is the case with Visual Basic. If you determine that implementing the operators does not make sense in your app context, it's also safe to suppress a warning from this rule when it fires on equality operators other than op_Equality. However, you should always override op_Equality and the == operator if you override <xref:System.Object.Equals%2A?displayProperty=nameWithType>.
76+
It's safe to suppress a warning from rule CA1036 when the violation is caused by missing operators and your programming language does not support operator overloading. If you determine that implementing the operators does not make sense in your app context, it's also safe to suppress a warning from this rule when it fires on equality operators other than `op_Equality`. However, you should always override `op_Equality` and the `==` operator if you override <xref:System.Object.Equals%2A?displayProperty=nameWithType>.
5577

5678
## Suppress a warning
5779

@@ -87,10 +109,12 @@ You can configure this option for just this rule, for all rules it applies to, o
87109
The following code contains a type that correctly implements <xref:System.IComparable>. Code comments identify the methods that satisfy various rules that are related to <xref:System.Object.Equals%2A> and the <xref:System.IComparable> interface.
88110

89111
:::code language="csharp" source="snippets/csharp/all-rules/ca1036.cs" id="snippet1":::
112+
:::code language="vb" source="snippets/vb/all-rules/ca1036.vb" id="snippet1":::
90113

91114
The following application code tests the behavior of the <xref:System.IComparable> implementation that was shown earlier.
92115

93116
:::code language="csharp" source="snippets/csharp/all-rules/ca1036.cs" id="snippet2":::
117+
:::code language="vb" source="snippets/vb/all-rules/ca1036.vb" id="snippet2":::
94118

95119
## See also
96120

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
TestCompare.Main1036("A", "B");
Lines changed: 98 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -1,143 +1,134 @@
11
using System;
22
using System.Globalization;
33

4-
namespace ca1036
4+
//<snippet1>
5+
// Valid ratings are between A and C.
6+
// A is the highest rating; it is greater than any other valid rating.
7+
// C is the lowest rating; it is less than any other valid rating.
8+
9+
public class RatingInformation : IComparable, IComparable<RatingInformation>
510
{
6-
//<snippet1>
7-
// Valid ratings are between A and C.
8-
// A is the highest rating; it is greater than any other valid rating.
9-
// C is the lowest rating; it is less than any other valid rating.
11+
public string Rating { get; private set; }
1012

11-
public class RatingInformation : IComparable, IComparable<RatingInformation>
13+
public RatingInformation(string rating)
1214
{
13-
public string Rating
14-
{
15-
get;
16-
private set;
17-
}
15+
ArgumentNullException.ThrowIfNull(rating);
1816

19-
public RatingInformation(string rating)
17+
string v = rating.ToUpper(CultureInfo.InvariantCulture);
18+
if (v.Length != 1 ||
19+
string.Compare(v, "C", StringComparison.Ordinal) > 0 ||
20+
string.Compare(v, "A", StringComparison.Ordinal) < 0)
2021
{
21-
if (rating == null)
22-
{
23-
throw new ArgumentNullException("rating");
24-
}
25-
26-
string v = rating.ToUpper(CultureInfo.InvariantCulture);
27-
if (v.Length != 1 || string.Compare(v, "C", StringComparison.Ordinal) > 0 || string.Compare(v, "A", StringComparison.Ordinal) < 0)
28-
{
29-
throw new ArgumentException("Invalid rating value was specified.", "rating");
30-
}
31-
32-
Rating = v;
22+
throw new ArgumentException("Invalid rating value was specified.", nameof(rating));
3323
}
3424

35-
public int CompareTo(object? obj)
36-
{
37-
if (obj == null)
38-
{
39-
return 1;
40-
}
41-
42-
if (obj is RatingInformation other)
43-
{
44-
return CompareTo(other);
45-
}
46-
47-
throw new ArgumentException("A RatingInformation object is required for comparison.", "obj");
48-
}
25+
Rating = v;
26+
}
4927

50-
public int CompareTo(RatingInformation? other)
28+
public int CompareTo(object? obj)
29+
{
30+
if (obj == null)
5131
{
52-
if (other is null)
53-
{
54-
return 1;
55-
}
56-
57-
// Ratings compare opposite to normal string order,
58-
// so reverse the value returned by String.CompareTo.
59-
return -string.Compare(this.Rating, other.Rating, StringComparison.OrdinalIgnoreCase);
32+
return 1;
6033
}
6134

62-
public static int Compare(RatingInformation left, RatingInformation right)
35+
if (obj is RatingInformation other)
6336
{
64-
if (object.ReferenceEquals(left, right))
65-
{
66-
return 0;
67-
}
68-
if (left is null)
69-
{
70-
return -1;
71-
}
72-
return left.CompareTo(right);
37+
return CompareTo(other);
7338
}
7439

75-
// Omitting Equals violates rule: OverrideMethodsOnComparableTypes.
76-
public override bool Equals(object? obj)
77-
{
78-
if (obj is RatingInformation other)
79-
{
80-
return this.CompareTo(other) == 0;
81-
}
82-
83-
return false;
84-
}
40+
throw new ArgumentException("A RatingInformation object is required for comparison.", nameof(obj));
41+
}
8542

86-
// Omitting getHashCode violates rule: OverrideGetHashCodeOnOverridingEquals.
87-
public override int GetHashCode()
43+
public int CompareTo(RatingInformation? other)
44+
{
45+
if (other is null)
8846
{
89-
char[] c = this.Rating.ToCharArray();
90-
return (int)c[0];
47+
return 1;
9148
}
9249

93-
// Omitting any of the following operator overloads
94-
// violates rule: OverrideMethodsOnComparableTypes.
95-
public static bool operator ==(RatingInformation left, RatingInformation right)
50+
// Ratings compare opposite to normal string order,
51+
// so reverse the value returned by String.CompareTo.
52+
return -string.Compare(Rating, other.Rating, StringComparison.OrdinalIgnoreCase);
53+
}
54+
55+
public static int Compare(RatingInformation left, RatingInformation right)
56+
{
57+
if (object.ReferenceEquals(left, right))
9658
{
97-
if (left is null)
98-
{
99-
return right is null;
100-
}
101-
return left.Equals(right);
59+
return 0;
10260
}
103-
public static bool operator !=(RatingInformation left, RatingInformation right)
61+
if (left is null)
10462
{
105-
return !(left == right);
63+
return -1;
10664
}
107-
public static bool operator <(RatingInformation left, RatingInformation right)
65+
return left.CompareTo(right);
66+
}
67+
68+
// Omitting Equals violates rule: OverrideMethodsOnComparableTypes.
69+
public override bool Equals(object? obj)
70+
{
71+
if (obj is RatingInformation other)
10872
{
109-
return (Compare(left, right) < 0);
73+
return CompareTo(other) == 0;
11074
}
111-
public static bool operator >(RatingInformation left, RatingInformation right)
75+
76+
return false;
77+
}
78+
79+
// Omitting getHashCode violates rule: OverrideGetHashCodeOnOverridingEquals.
80+
public override int GetHashCode()
81+
{
82+
char[] c = Rating.ToCharArray();
83+
return (int)c[0];
84+
}
85+
86+
// Omitting any of the following operator overloads
87+
// violates rule: OverrideMethodsOnComparableTypes.
88+
public static bool operator ==(RatingInformation left, RatingInformation right)
89+
{
90+
if (left is null)
11291
{
113-
return (Compare(left, right) > 0);
92+
return right is null;
11493
}
94+
return left.Equals(right);
11595
}
116-
//</snippet1>
96+
public static bool operator !=(RatingInformation left, RatingInformation right)
97+
{
98+
return !(left == right);
99+
}
100+
public static bool operator <(RatingInformation left, RatingInformation right)
101+
{
102+
return (Compare(left, right) < 0);
103+
}
104+
public static bool operator >(RatingInformation left, RatingInformation right)
105+
{
106+
return (Compare(left, right) > 0);
107+
}
108+
}
109+
//</snippet1>
117110

118-
//<snippet2>
119-
public class Test
111+
//<snippet2>
112+
public class TestCompare
113+
{
114+
public static void Main1036(params string[] args)
120115
{
121-
public static void Main1036(string[] args)
116+
if (args.Length < 2)
122117
{
123-
if (args.Length < 2)
124-
{
125-
Console.WriteLine("usage - TestRatings string 1 string2");
126-
return;
127-
}
128-
RatingInformation r1 = new RatingInformation(args[0]);
129-
RatingInformation r2 = new RatingInformation(args[1]);
130-
string answer;
131-
132-
if (r1.CompareTo(r2) > 0)
133-
answer = "greater than";
134-
else if (r1.CompareTo(r2) < 0)
135-
answer = "less than";
136-
else
137-
answer = "equal to";
138-
139-
Console.WriteLine("{0} is {1} {2}", r1.Rating, answer, r2.Rating);
118+
return;
140119
}
120+
RatingInformation r1 = new(args[0]);
121+
RatingInformation r2 = new(args[1]);
122+
string answer;
123+
124+
if (r1.CompareTo(r2) > 0)
125+
answer = "greater than";
126+
else if (r1.CompareTo(r2) < 0)
127+
answer = "less than";
128+
else
129+
answer = "equal to";
130+
131+
Console.WriteLine("{0} is {1} {2}", r1.Rating, answer, r2.Rating);
141132
}
142-
//</snippet2>
143133
}
134+
//</snippet2>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Public Class Program
2+
Public Shared Sub Main()
3+
TestCompare.Main1036(New String() {"C", "B"})
4+
End Sub
5+
End Class

docs/fundamentals/code-analysis/quality-rules/snippets/vb/all-rules/all-rules.vbproj

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,9 @@
44
<OutputType>Exe</OutputType>
55
<RootNamespace>all_rules</RootNamespace>
66
<TargetFramework>net8.0</TargetFramework>
7+
<NoWarn>$(NoWarn);SYSLIB0050</NoWarn>
78
</PropertyGroup>
89

9-
<ItemGroup>
10-
<Compile Remove="Program.vb" />
11-
</ItemGroup>
12-
1310
<ItemGroup>
1411
<PackageReference Include="System.Data.SqlClient" Version="4.8.6" />
1512
<PackageReference Include="System.Security.Permissions" Version="8.0.0" />

docs/fundamentals/code-analysis/quality-rules/snippets/vb/all-rules/ca1003-use-generic-event-handler-instances_1.vb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ Namespace ca1003
4242

4343
Class Test
4444

45-
Shared Sub Main()
45+
Shared Sub Main1003()
4646

4747
Dim eventRaiser As New ClassThatRaisesEvent()
4848
Dim eventHandler As New ClassThatHandlesEvent(eventRaiser)

0 commit comments

Comments
 (0)