Navigation

Gendarme.Rules.Design

From Mono

Gendarme's design rules are located in the Gendarme.Rules.Design.dll assembly. Latest sources are available from anonymous SVN (http://anonsvn.mono-project.com/viewcvs/trunk/mono-tools/gendarme/rules/Gendarme.Rules.Design/) (tarball (http://anonsvn.mono-project.com/viewcvs/trunk/mono-tools/gendarme/rules/Gendarme.Rules.Design.tar.gz?view=tar)).

Table of contents

Rules

AbstractTypesShouldNotHavePublicConstructorsRule

This rule ensure that all abstract type do not have public constructor since they cannot be used.

Bad example:

abstract public class MyClass {
   public MyClass ()
   {
   }
}

Good example:

abstract public class MyClass {
   protected MyClass ()
   {
   }
}

AttributeArgumentsShouldHaveAccessorsRule

All parameters passed to the attribute constructor must be visible through properties with properly cased names (e.g. myValue parameter would map to MyValue property).

Bad example:

[AttributeUsage (AttributeTargets.All)]
public sealed class AttributeWithRequiredProperties : Attribute {
   private int storedFoo;
   private string storedBar;
 
   // we have no corresponding property with the name 'Bar' so the rule will fail
   public AttributeWithRequiredProperties (int foo, string bar)
   {
      storedFoo = foo;
      storedBar = bar; 
   }
 
   public int Foo {
      get { return storedFoo; }
   }
}

Good example:

[AttributeUsage (AttributeTargets.All)]
public sealed class AttributeWithRequiredProperties : Attribute {
   private int storedFoo;
   private string storedBar;
 
   public AttributeWithRequiredProperties (int foo, string bar)
   {
      storedFoo = foo;
      storedBar = bar;
   }
 
   public int Foo {
      get { return storedFoo; }
   }
 
   public string Bar {
      get { return storedBar; }
   }
}

AvoidEmptyInterfaceRule

The rule check interface to ensure they are not empty. Empty interface don't add anything useful and in many case are used as a marker on a type. For the last case it is more elegant to define and use an attribute.

Bad example:

public interface IMarker {
}
 
public class MyClass : IMarker {
}

Good example:

[MarkedByAnAttribute]
public class MyClass {
}

AvoidPropertiesWithoutGetAccessorRule

The rule ensure that all properties that have setters also have a getter. Properties without get are often confusing to developers. In some case it's better to add a getter, while in other cases the property can be replaced with a method.

Bad examples:

public double X {
   // no get since it's not really required
   set { x = value; }
}
 
public sting Password {
   // no get as we don't want to expose the password
   set { password = value; }
}

Good example:

public double X {
   get { return x; }
   set { x = value; }
}
 
public void SetPassword (string value)
{
   password = value;
}

AvoidPublicInstanceFieldsRule

In most cases, it is usually better to have public properties, rather than public instance fields.

Bad example:

public class Foo
{
   public int Value;
}

Good example:

public class Foo {
   private int v;
   public int Value {
	get { return v; }
	set { v = value; }
   }
}

ConsiderConvertingMethodToPropertyRule

Methods which function similarly to properties should be converted into properties. For example, member functions beginning with "Is", "Get", or "Set" are likely candidates.

Bad example:

public int GetFoo ()
{
   return foo;
}
 
public bool IsBar ()
{
   return bar;
}

Good example:

public int Foo {
   get { return foo; }
}
 
public bool IsBar {
   get { return bar; }
}

DisposableFieldsShouldBeDisposedRule

The rule inspects all fields for disposable types and, if IDisposable is implemented, check that the Dispose method does indeed call Dispose on all the fields (that implements IDisposable).

Bad example:

class DoesNotDisposeMember : IDisposable {
   byte[] buffer;
   IDisposable field;
 
   public void Dispose ()
   {
      buffer = null;
      // field is not disposed
   }
}

Good examples:

class CallsDispose : IDisposable {
   byte[] buffer;
   IDisposable field;
 
   public void Dispose ()
   {
      buffer = null;
      field.Dispose ();
   }
}
class DisposePattern : IDisposable {
   byte[] buffer;
   IDisposable field;
   bool disposed;
    
   public void Dispose ()
   {
      Dispose (true);
   }
 
   private void Dispose (bool disposing)
   {
      if (disposed)
         return;
      if (disposing) {
         field.Dispose ();
         buffer = null;
      }
      disposed = true;
   }
}

DisposableTypesShouldHaveFinalizerRule

The rule inspects all fields for native types and reports an error if the type doesn't have a finalizer (destructor).

Bad example:

class NoFinalizer {
   IntPtr field;
}

Good example:

class HasFinalizer {
   IntPtr field;
 
   ~HasFinalizer ()
   {
      UnmanagedFree (field);
   }
}

EnsureSymmetryForOverloadedOperatorsRule

This rule checks for operators that are not overloaded in pairs. The C# compiler forces you to implement some of the pairs, but other languages might not. The following pairs are checked:

Warnings:

  • Addition / Subtraction
  • Multiply / Division
  • Division / Modulus

Errors:

  • Equality / InEquality
  • True / False
  • GreaterThan / LessThan
  • GreaterThanOrEqual / LessThanOrEqual

Bad example:

class DoesNotOverloadAdd {
   public static int operator - (DoesNotOverloadOperatorEquals a)
   {
      return 0;
   }
}

Good example:

struct OverloadsAdd {
   public static int operator + (OverloadsOperatorEquals a)
   {
      return 0;
   }
 
   public static int operator - (OverloadsOperatorEquals a)
   {
      return 0;
   }
}

EnumsShouldDefineAZeroValueRule

This rule ensure that every enumeration, that are not flags, contains a 0 value usable as the default value.

Bad example:

enum Position {
   First = 1,
   Second
}

Good example:

enum Position {
   First,
   Second
}

EnumsShouldUseInt32Rule

NOTE: At current time this rule is only available from our SVN repository. The next release of Gendarme will include this rule.

Enumaration types should avoid specifying a non-default storage type for their values, unless it is used and required for interoperability. In the later case non-CLS compliant types should be avoided to ensure the code can be reused by all CLS-compliant languages.

Bad examples:

public enum SmallEnum : byte {
   Zero,
   One
}
 
[Flags]
public enum SmallFlag : ushort {
   One = 1,
   // ...
   Sixteen = 1 << 15
}

Good example:

public enum SmallEnum {
   Zero,
   One
}
 
[Flags]
public enum SmallFlag {
   One = 1,
   // ...
   Sixteen = 1 << 15
}

FlagsShouldNotDefineAZeroValueRule


This rule ensure that every flags (enumeration) does not contain a 0 value. This value would not be usable in boolean operations.

Bad example:

[Flags]
enum Access {
   None = 0,
   Read = 1,
   Write = 2
}

Good example:

[Flags]
enum Access {
   Read = 1,
   Write = 2
}

FinalizersShouldBeProtectedRule

All finalizers must be protected because otherwise they can be called from the user code. In C# this is enforced by compiler, but some languages may not have such a restriction, thus making developer able to declare non-protected finalizers.

Good example:

public class GoodProtectedFinalizer {
   // compiler makes it protected
   ~GoodProtectedFinalizer ()
   {
   }
}
.class family auto ansi beforefieldinit GoodProtectedFinalizer extends
[mscorlib]System.Object
{
   .method family hidebysig instance void Finalize() cil managed
   {
      // ...
   }
}

Bad example (IL):

.class family auto ansi beforefieldinit BadPublicFinalizer extends
[mscorlib]System.Object
{
   .method public hidebysig instance void Finalize() cil managed
   {
      // ...
   }
}

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 may allow such behavior, which should not be allowed.

Good example:

public class GoodFinalizer {
   ~GoodFinalizer () 
   {
      // C# compiler will insert base.Finalize () call here
      // so any compiler-generated code will be valid
   }
}

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

ImplementGenericCollectionInterfacesRule

NOTE: At current time this rule is only available from our SVN repository. The next release of Gendarme will include this rule.

This rule warns developer about publicly visible types that implement IEnumerable interface but do not implement its generic equivalent IEnumerable<T>. Usage of generic interfaces is preferable since it makes collections type-safe and more flexible. Types declared in assemblies compiled against .NET Framework version 1.0 or 1.1 are not affected by this rule, as well as the types that implement IDictionary interface.

Bad example:

public class NoUseOfGenerics : IEnumerable {
   public IEnumerator GetEnumerator ()
   {
      // ...
   }
}

Good example:

public class GenericsAreUsed : IEnumerable<Dog> {
 
   public IEnumerator<Dog> GetEnumerator ()
   {
      // ...
   }
 
   IEnumerator IEnumerable.GetEnumerator ()
   {
      // ...
   }
}

UsingCloneWithoutImplementingICloneableRule

This rule warns every time you implement a Clone(object) method without implementing the ICloneable interface. Either implement the interface or, if possible, change the return type to the type definition (since this will avoid unnecessary casts).

Note: Make sure to document the behavior of your Clone method since the framework itself is not very clear, or consistent, between shallow and deep cloning.

Bad example:

public class MyClass {
   public object Clone ()
   {
      MyClass myClass = new MyClass ();
      return myClass;
   }
}

Good examples:

public class MyClass : ICloneable {
   public object Clone ()
   {
      MyClass myClass = new MyClass ();
      return myClass;
   } 
}

or

public class MyClass {
   public MyClass Clone ()
   {
      MyClass myClass = new MyClass ();
      return myClass;
   } 
}

DontDeclareProtectedFieldsInSealedClassRule

This rule ensure that sealed types (classes that you can't inherit from) don't define protected fields (which would only be useful in subclasses).

Bad example:

public sealed class MyClass {
   protected int someValue;
}

Good example:

public sealed class MyClass {
   private int someValue; 
}

OperatorEqualsShouldBeOverloadedRule

This rule checks if the operators add (+) and subtract (-) are overloaded or if a value type overrides Object.Equals and warns if the equals (==) operator is not overloaded.

Bad examples:

class DoesNotOverloadOperatorEquals {
   public static int operator + (DoesNotOverloadOperatorEquals a)
   {
      return 0;
   }
 
   public static int operator - (DoesNotOverloadOperatorEquals a)
   {
      return 0;
   }
}
struct OverridesEquals {
   public override bool Equals (object obj)
   {
      return base.Equals (obj);
   }
}

Good example:

struct OverloadsOperatorEquals {
   public static int operator + (OverloadsOperatorEquals a)
   {
      return 0;
   }
 
   public static int operator - (OverloadsOperatorEquals a)
   {
      return 0;
   }
 
   public static bool operator == (OverloadsOperatorEquals a, OverloadsOperatorEquals b)
   {
      return a.Equals (b);
   }
 
   public override bool Equals (object obj)
   {
      return base.Equals (obj);
   }
}

OverrideEqualsMethodRule

This rule generates a warning if a type overloads the equality (==) operator but does not override the Object.Equals method.

Bad example:

class DoesNotOverrideEquals {
   public static bool operator == (DoesNotOverloadOperatorEquals a, DoesNotOverloadOperatorEquals b)
   {
      return true;
   }
}

Good example:

class OverridesEquals {
   public static bool operator == (DoesNotOverloadOperatorEquals a, DoesNotOverloadOperatorEquals b)
   {
      return true;
   }
	
   public override bool Equals (object obj)
   {
      OverridesEquals other = (obj as OverridesEquals);
      if (other == null)
         return false;
 
      return (this == other);
   }
}

ProvideAlternativeNamesForOperatorOverloadsRule

Some languages (like VB.NET) cannot use overloaded operators. For those languages named methods should be implemented that provide the same functionality. This rule checks for a named alternative for each overloaded operator.

  • op_UnaryPlus => "Plus"
  • op_UnaryNegation => "Negate"
  • op_LogicalNot => "LogicalNot"
  • op_OnesComplement => "OnesComplement"
  • op_Increment => "Increment"
  • op_Decrement => "Decrement"
  • op_True => "IsTrue"
  • op_False => "IsFalse"
  • op_Addition => "Add"
  • op_Subtraction => "Subtract"
  • op_Multiply => "Multiply"
  • op_Division => "Divide"
  • op_Modulus => "Modulus"
  • op_BitwiseAnd => "BitwiseAnd"
  • op_BitwiseOr => "BitwiseOr"
  • op_ExclusiveOr => "ExclusiveOr"
  • op_LeftShift => "LeftShift"
  • op_RightShift => "RightShift"
  • op_Inequality => (not) "Equals"
  • op_GreaterThan => "Compare"
  • op_LessThan => "Compare"
  • op_GreaterThanOrEqual => "Compare"
  • op_LessThanOrEqual => "Compare"

Bad example:

class DoesNotImplementAlternative {
   public static int operator + (DoesNotOverloadOperatorEquals a, DoesNotOverloadOperatorEquals b)
   {
      return 0;
   }
}

Good example:

class DoesImplementAdd {
   public static int operator + (DoesNotOverloadOperatorEquals a, DoesNotOverloadOperatorEquals b)
   {
      return 0;
   }
 
   public int Add (DoesNotOverloadOperatorEquals a)
   {
      return this + a;
   }
}

MainShouldNotBePublicRule

This rule is used to warn developer if assembly's entry point (so-called Main method) is exposed to other assemblies as a public method and can be accessed by them. It is recommended to make it private to make sure that it can be called only by CLR itself while executing the code.

Bad example:

public class MainClass {
   public void Main ()
   {
   }
}

Good examples:

internal class MainClass {
   public void Main ()
   {
   }
}
public class MainClass {
   internal void Main ()
   {
   }
}

MissingAttributeUsageOnCustomAttributeRule

Every custom attribute should be decorated with [AttributeUsage] attribute to specify to which kind of code members it can be applied.

Bad example:

public sealed class SomeAttribute : Attribute {
}

Good examples:

[AttributeUsage (AttributeTargets.All)]
public sealed class AttributeApplyingToAnything : Attribute {
}
[AttributeUsage (AttributeTargets.Field)]
public sealed class AttributeApplyingToFields : Attribute {
}

TypesShouldBeInsideNamespacesRule

The rule ensure that all types are declared inside a namespace. This avoid potential duplicates when several assemblies are used.

Bad example:

using System;
 
public class Configuration {
}

Good example:

using System;
 
namespace My.Stuff {
   public class Configuration {
   }
}

TypesWithDisposableFieldsShouldBeDisposableRule

If a type has fields that implement IDisposable, the type should also implement IDisposable to dispose those fields correctly.

Bad examples:

class DoesNotImplementIDisposable {
    IDisposable field;
}
class AbstractDispose : IDisposable {
    IDisposable field;
    public abstract void Dispose ();
}

Good example:

class Dispose : IDisposable {
   IDisposable field;
 
   public void Dispose ()
   {
      field.Dispose ();
   }
}

TypesWithNativeFieldsShouldBeDisposableRule

The rule inspects all fields in a type for it's use of specific native types, like IntPtr, UIntPtr and HandleRef. If so the rule warns if the type itself doesn't implement IDisposable.

Bad examples:

class DoesNotImplementIDisposable {
   IntPtr field;
}
class AbstractDispose : IDisposable {
   IntPtr field;
   public abstract void Dispose ();
}

Good example:

class Dispose : IDisposable {
   IDisposable field;
   public void Dispose ()
   {
      UnmanagedFree (field);
   }
}

Feedback

Please report any documentation errors, typos or suggestions to the Gendarme Google Group (http://groups.google.com/group/gendarme). Thanks!