Gendarme.Rules.Correctness

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/) (tarball (http://anonsvn.mono-project.com/viewcvs/trunk/mono-tools/gendarme/rules/Gendarme.Rules.Correctness.tar.gz?view=tar)).

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:

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));
}

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!");
}

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

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!");
string s2 = String.Format ("Hello {0}!"); // no argument to back {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

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

ReviewIntegerDivisionRule

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

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!