Gendarme's correctness rules are located in the Gendarme.Rules.Correctness.dll assembly. Latest sources are available from anonymous SVN (http://anonsvn.mono-project.com/viewcvs/trunk/mono-tools/gendarme/rules/Gendarme.Rules.Correctness/).
Table of Contents
1.1 AttributeStringLiteralsShouldParseCorrectlyRule
1.2 AvoidConstructorsInStaticTypesRule
1.3 AvoidFloatingPointEqualityRule
1.4 BadRecursiveInvocationRule
1.5 CallingEqualsWithNullArgRule
1.6 DisposableFieldsShouldBeDisposedRule
1.7 DoNotCompareWithNaNRule
1.8 DoNotRecurseInEqualityRule
1.9 DoNotRoundIntegersRule
1.10 EnsureLocalDisposalRule
1.11 FinalizersShouldCallBaseClassFinalizerRule
1.12 MethodCanBeMadeStaticRule
1.13 ProvideCorrectArgumentsToFormattingMethodsRule
1.14 ProvideCorrectRegexPatternRule
1.15 ReviewCastOnIntegerDivisionRule
1.16 ReviewCastOnIntegerMultiplicationRule
1.17 ReviewDoubleAssignmentRule
1.18 ReviewInconsistentIdentityRule
1.19 ReviewSelfAssignmentRule
1.20 ReviewUselessControlFlowRule
1.21 ReviewUseOfInt64BitsToDoubleRule
1.22 ReviewUseOfModuloOneOnIntegersRule
1.23 UseValueInPropertySetterRule
Rules
AttributeStringLiteralsShouldParseCorrectlyRule
As attributes are used at compile time, only constants can be passed to constructors. You can use an URI but you have to pass the URI as an string, and this can lead you at some errors at run time. This rule checks attributes with the following types, represented as a string, and validate their contents:
- Version
- Guid
- Uri
Bad example:
[assembly: AssemblyFileVersion ("fooo")]
Good example:
[assembly: AssemblyFileVersion ("0.0.1.*")]
Notes
- This rule is available since Gendarme 2.2
AvoidConstructorsInStaticTypesRule
This rule check for types that contains only static members and warn if a visible instance constructor is present in it. This was a common mistake in the framework 1.x since C# adds a default, public, constructor when none is provided. Code using the framework 2.0 (and later) should change this type, if possible, into a static type.
Bad example:
// it is possible to instantiate this class since the // C# compiler adds a default, public, constructor public class Class { public static void Method () { } }
Good example:
public class Class { // this class cannot be instantiated private Class () { } public static void Method () { } }
AvoidFloatingPointEqualityRule
Comparing floating points values isn't easy, because simple values, such as 0.2, cannot be precisely represented. This rule ensures the code doesn't contains floating point [in]equality comparison for Single and Double values. For more information:
- Floating Point Comparison (General Problem) (http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm)
- Another article about floating point comparison (more .NET adapted) (http://www.yoda.arachsys.com/csharp/floatingpoint.html)
Bad example:
void AMethod () { float f1 = 0.1; float f2 = 0.001 * 100; if (f1 == f2) { // ^^^ this equality can be false ! } }
Good example (delta):
const float delta = 0.000001; void AMethod () { float f1 = 0.1; float f2 = 0.001 * 100; if (Math.Abs (f1 - f2) < delta) { // this will work with known value but in real-life // you may hit [Positive|Negative]Infinity and NaN } }
Good example (decimal):
void BMethod () { decimal d1 = 0.1m; decimal d2 = 0.001m * 100; // decimals are slower but keep their precision if (d1 == d2) { } }
Notes
- Prior to Gendarme 2.2 this rule was named FloatComparisonRule.
BadRecursiveInvocationRule
This rule catches a common mistake in programs when a method or property invokes itself recursively in a suspicious way. Usually the developer forgot to return a variable, or call a base method.
Bad example:
string CurrentDirectory { get { return CurrentDirectory; } }
Good example:
string CurrentDirectory { get { return base.CurrentDirectory; } }
CallingEqualsWithNullArgRule
This rule checks for methods that Equals with a null real parameter. Such calls should always return false.
Bad example:
public void MakeStuff () { MyClass myClassInstance = new MyClass (); MyClass otherClassInstance = null; Console.WriteLine (myClassInstance.Equals (otherClassInstance)); }
Good example:
public void MakeStuff () { MyClass myClassInstance = new MyClass (); MyClass otherClassInstance = new MyClass (); Console.WriteLine (myClassInstance.Equals (otherClassInstance)); }
DisposableFieldsShouldBeDisposedRule
The rule inspects all fields for disposable types and, if System.IDisposableis implemented, check that the type Dispose method does indeed call Disposeon all the fields (that implements System.IDisposable).
Bad example:
class DoesNotDisposeMember : IDisposable { byte[] buffer; IDisposable field; public void Dispose () { buffer = null; // field is not disposed } }
Good example:
class DisposePattern : IDisposable { byte[] buffer; IDisposable field; bool disposed; public void Dispose () { Dispose (true); } private void Dispose (bool disposing) { if (!disposed) { if (disposing) { field.Dispose (); } buffer = null; disposed = true; } } }
DoNotCompareWithNaNRule
As defined in IEEE 754 it's impossible to compare any floating-point value, even another NaN, with NaN. Such comparison will always return false(more information on wikipedia (http://en.wikipedia.org/wiki/NaN)). The framework provides methods, Single.IsNaN and Double.IsNaN, to check for NaN values.
Bad example:
double d = ComplexCalculation (); if (d == Double.NaN) { // this will never be reached, even if d is NaN Console.WriteLine ("No solution exists!"); }
Good example:
double d = ComplexCalculation (); if (Double.IsNaN (d)) { Console.WriteLine ("No solution exists!"); }
DoNotRecurseInEqualityRule
An operator== or operator!= method is calling itself recursively. This is usually caused by neglecting to cast an argument to System.Object before comparing it to null.
Bad example:
public static bool operator== (Customer lhs, Customer rhs) { if (object.ReferenceEquals (lhs, rhs)) { return true; } if (lhs == null || rhs == null) { return false; } return lhs.name == rhs.name && lhs.address == rhs.address; }
Good example:
public static bool operator== (Customer lhs, Customer rhs) { if (object.ReferenceEquals (lhs, rhs)) { return true; } if ((object) lhs == null || (object) rhs == null) { return false; } return lhs.name == rhs.name && lhs.address == rhs.address; }
Notes
- This rule is available since Gendarme 2.4
DoNotRoundIntegersRule
This rule check for attempts to call Round, Ceiling, Floor or Truncate on an integral type. This often indicate a typo in the source code (e.g. wrong variable) or simply an unneeded operation.
Bad example:
public decimal Compute (int x) { return Math.Truncate ((decimal) x); }
Good example:
public decimal Compute (int x) { return (decimal) x; }
Notes
- This rule is available since Gendarme 2.0
EnsureLocalDisposalRule
This rule checks that disposable locals are always disposed of before the method returns. Use a 'using' statement (or a try/finally block) to guarantee local disposal even in the event an unhandled exception occurs.
Bad example (non-guaranteed disposal):
void DecodeFile (string file) { var stream = new StreamReader (file); DecodeHeader (stream); if (!DecodedHeader.HasContent) { return; } DecodeContent (stream); stream.Dispose (); }
Good example (non-guaranteed disposal):
void DecodeFile (string file) { using (var stream = new StreamReader (file)) { DecodeHeader (stream); if (!DecodedHeader.HasContent) { return; } DecodeContent (stream); } }
Bad example (not disposed of / not locally disposed of):
void DecodeFile (string file) { var stream = new StreamReader (file); Decode (stream); } void Decode (Stream stream) { /*code to decode the stream*/ stream.Dispose (); }
Good example (not disposed of / not locally disposed of):
void DecodeFile (string file) { using (var stream = new StreamReader (file)) { Decode (stream); } } void Decode (Stream stream) { /*code to decode the stream*/ }
Notes
- This rule is available since Gendarme 2.4
FinalizersShouldCallBaseClassFinalizerRule
This rule is used to warn the developer if a finalizer does not call base class finalizer. In C#, this is enforced by compiler but some .NET languages (like IL) may allow such behavior, which should not be allowed.
Bad example (IL):
.assembly extern mscorlib { .ver 1:0:5000:0 .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) } .class public auto ansi beforefieldinit BadFinalizer extends [mscorlib]System.Object { .method family virtual hidebysig instance void Finalize() cil managed { // no base call so rule will fire here } }
Good example (C#):
public class GoodFinalizer { ~GoodFinalizer () { // C# compiler will insert base.Finalize () call here // so any compiler-generated code will be valid } }
MethodCanBeMadeStaticRule
This rule checks for methods that do not require anything from the current instance. Those methods can be converted into static methods, which helps a bit the performance (the hidden this parameter can be omitted), and clarify the API.
Bad example:
public class Bad { private int x, y, z; bool Valid (int value) { // the validation has no need to know the instance values return (value > 0); } public int X { get { return x; } set { if (!Valid (value)) { throw ArgumentException ("X"); } x = value; } } // same for Y and Z }
Good example:
public class Good { private int x, y, z; static bool Valid (int value) { return (value > 0); } // same X (and Y and Z) as before }
ProvideCorrectArgumentsToFormattingMethodsRule
This rule checks that the format string provided to String.Format calls match with its parameters.
Bad examples:
string s1 = String.Format ("There is nothing to format here!"); // no argument to back {0} string s2 = String.Format ("Hello {0}!");
Good examples:
string s1 = "There is nothing to format here!"; string s2 = String.Format ("Hello {0}!", name);
Notes
- This rule is available since Gendarme 2.2
ProvideCorrectRegexPatternRule
This rule checks if methods/constructors requiring a regular expression string are provided a valid pattern.
Bad example:
//Invalid end of pattern Regex re = new Regex ("^\\");
Good example:
Regex re = new Regex (@"^\\");
Bad example:
//Unterminated [] set Regex re = new Regex ("([a-z)*");
Good example:
Regex re = new Regex ("([a-z])*");
Bad example:
//Reference to undefined group number 2 return Regex.IsMatch (code, @"(\w)-\2");
Good example:
return Regex.IsMatch (code, @"(\w)-\1");
Notes
- This rule is available since Gendarme 2.4
ReviewCastOnIntegerDivisionRule
This rule checks when the result of a division between integral types is casted into a floating point type. Casting the result, instead of the operands, converts the integer result into a floating point value - i.e. the result is truncated.
Bad example:
public double Bad (int a, int b) { // integers are divided, then the result is casted into a double // i.e. Bad (5, 2) == 2.0d return a / b; }
Good example:
public double Good (int a, int b) { // a double is divided by an integer, which result in a double result // i.e. Good (5, 2) == 2.5d return (double) a / b; }
Notes
- This rule is available since Gendarme 2.2
ReviewCastOnIntegerMultiplicationRule
This rule checks when the result of a multiplication between integral types is casted into a larger integral type. Casting the result, instead of the operands, converts the computed result into the new type - the multiplication operation is still done with the smaller type.
Bad example:
public long Bad (int a, int b) { // e.g. Bad (Int32.MaxInt, Int32.MaxInt) == 1 return a * b; }
Good example:
public long Good (int a, int b) { // e.g. Good (Int32.MaxInt, Int32.MaxInt) == 4611686014132420609 return (long) a * b; }
Notes
- This rule is available since Gendarme 2.2
ReviewDoubleAssignmentRule
This rule checks for variables or fields that are assigned multiple times to the same value. This never change the value of the variable (or fields) but should be reviewed since it could be a typo that hides a real issue in the code.
Bad example:
public class Bad { private int x, y; public Bad (int value) { // x is assigned twice, but y is not assigned x = x = value; } }
Good example:
public class Good { private int x, y; public Good (int value) { // x = y = value; was the original meaning but since it's confusing... x = value; y = value; } }
Notes
- This rule is available since Gendarme 2.0
ReviewInconsistentIdentityRule
This rule checks to see if a type is managing its identity in a consistent way. It checks:
- Equals methods, relational operators and CompareTo must either use the same set of fields and properties or call a helper method.
- GetHashCode must use the same or a subset of the fields used by the equality methods or call a helper method.
- Clone must use the same or a superset of the fields used by the equality methods or call a helper method.
Notes
- This rule is available since Gendarme 2.4
ReviewSelfAssignmentRule
This rule checks for variables or fields that are assigned to themselves. This never change the value of the variable (or fields) but should be reviewed since it could be a typo that hides a real issue in the code.
Bad example:
public class Bad { private int value; public Bad (int value) { // argument is assigned to itself, this.value is unchanged value = value; } }
Good example:
public class Good { private int value; public Good (int value) { this.value = value; } }
Notes
- This rule is available since Gendarme 2.0
ReviewUselessControlFlowRule
This rule checks for empty blocks that produce uneless control flow inside IL. This usually occurs when a block is left incomplete or when a typo is made.
Bad example (empty):
if (x == 0) { // TODO - ever seen such a thing ? ;-) }
Bad example (typo):
if (x == 0); { Console.WriteLine ("always printed"); }
Good example:
if (x == 0) { Console.WriteLine ("printed only if x == 0"); }
Notes
- This rule is available since Gendarme 2.0
ReviewUseOfInt64BitsToDoubleRule
This rule checks for invalid integer to double conversion using the, confusinsly named, BitConverter.Int64BitsToDouble method. This methods converts the actual bits, i.e. not the value, into a Double. The rule will warn when anything else than an Int64 is being used as a parameter to this method.
Bad example:
public double GetRadians (int degrees) { return BitConverter.Int64BitsToDouble (degrees) * Math.PI / 180.0d; }
Good example:
public double GetRadians (int degree) { return degrees * Math.PI / 180.0d; }
Notes
- This rule is available since Gendarme 2.0
ReviewUseOfModuloOneOnIntegersRule
This rule checks for a modulo one (1) operation on an integral type. This is most likely a typo since the answer is always 0. This usually happen when someone confuse a bitwise operation with a remainder.
Bad example:
public bool IsOdd (int i) { return ((i % 1) == 1); }
Good example:
public bool IsOdd (int i) { return ((i % 2) != 0); // or ((x & 1) == 1) }
Notes
- This rule is available since Gendarme 2.0
UseValueInPropertySetterRule
This rule ensures all setter properties uses the value argument passed to the property.
Bad example:
public bool Active { get { return active; } // this can take a long time to figure out if the default value for active // is false (since most people will use the property to set it to true) set { active = true; } }
Good example:
public bool Active { get { return active; } set { active = value; } }
Feedback
Please report any documentation errors, typos or suggestions to the Gendarme Google Group (http://groups.google.com/group/gendarme). Thanks!


