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/).
Table of Contents
1.1 AbstractTypesShouldNotHavePublicConstructorsRule
1.2 AttributeArgumentsShouldHaveAccessorsRule
1.3 AvoidEmptyInterfaceRule
1.4 AvoidMultidimensionalIndexerRule
1.5 AvoidPropertiesWithoutGetAccessorRule
1.6 AvoidRefAndOutParametersRule
1.7 AvoidSmallNamespaceRule
1.8 AvoidVisibleFieldsRule
1.9 AvoidVisibleNestedTypesRule
1.10 ConsiderAddingInterfaceRule
1.11 ConsiderConvertingFieldToNullableRule
1.12 ConsiderConvertingMethodToPropertyRule
1.13 ConsiderUsingStaticTypeRule
1.14 DeclareEventHandlersCorrectlyRule
1.15 DisposableTypesShouldHaveFinalizerRule
1.16 DoNotDeclareProtectedMembersInSealedTypeRule
1.17 DoNotDeclareVirtualMethodsInSealedTypeRule
1.18 EnsureSymmetryForOverloadedOperatorsRule
1.19 EnumsShouldDefineAZeroValueRule
1.20 EnumsShouldUseInt32Rule
1.21 FinalizersShouldBeProtectedRule
1.22 FlagsShouldNotDefineAZeroValueRule
1.23 ImplementEqualsAndGetHashCodeInPairRule
1.24 ImplementICloneableCorrectlyRule
1.25 ImplementIComparableCorrectlyRule
1.26 InternalNamespacesShouldNotExposeTypesRule
1.27 MainShouldNotBePublicRule
1.28 MarkAssemblyWithAssemblyVersionRule
1.29 MarkAssemblyWithCLSCompliantRule
1.30 MarkAssemblyWithComVisibleRule
1.31 MissingAttributeUsageOnCustomAttributeRule
1.32 OperatorEqualsShouldBeOverloadedRule
1.33 OverrideEqualsMethodRule
1.34 PreferEventsOverMethodsRule
1.35 PreferIntegerOrStringForIndexersRule
1.36 ProvideAlternativeNamesForOperatorOverloadsRule
1.37 TypesShouldBeInsideNamespacesRule
1.38 TypesWithDisposableFieldsShouldBeDisposableRule
1.39 TypesWithNativeFieldsShouldBeDisposableRule
Rules
AbstractTypesShouldNotHavePublicConstructorsRule
This rule ensure that abstract types do not have public constructor since they cannot be instantied by user code. Changing the constructor(s) visibility to protected keeps the type functionality identical and makes it clear that the type is there to be inherited from.
Bad example:
abstract public class MyClass { public MyClass () { } }
Good example:
abstract public class MyClass { protected MyClass () { } }
AttributeArgumentsShouldHaveAccessorsRule
This rule ensure that all parameters passed to an Attribute constructor must be visible through properties with properly cased names.
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
This rule checks every interface to ensure they are not empty. Empty interface don't add anything useful and in many case are only 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 { }
AvoidMultidimensionalIndexerRule
This rule checks for indexer properties that use more than one index on visible types. Such indexers are often confusing to use (e.g. index orders) and are better represented by a method.
Bad example:
public int this [int x, int y] { get { return 0; } }
Good example:
public int Get (int x, int y) { return 0; }
Notes
- This rule is available since Gendarme 2.0
AvoidPropertiesWithoutGetAccessorRule
This rule checks for indexer properties that use more than one index on visible types. Such indexers are often confusing to use (e.g. index orders) and are better represented by a method.
Bad examples:
public double Seed { // no get since there's no use case for it set { seed = value; } } public sting Password { // no get as we don't want to expose the password set { password = value; } }
Good examples:
public double Seed { get { return seed; } set { seed = value; } } public void SetPassword (string value) { password = value; }
AvoidRefAndOutParametersRule
This rule checks for methods that use ref or out parameters. They are powerful features that can easily be misunderstood (by the consumer) and misused (by the consumer) to create hard to use API. Avoid them whenever possible or, if needed, provide simpler alternatives coverage most use cases. An exception is made, i.e. no defect are reported, for the bool Try*(X out) pattern.
Bad example:
public bool NextJob (ref int id, out string display) { if (id < 0) return false; display = String.Format ("Job #{0}", id++); return true; }
Good example:
private int id = 0; private int GetNextId () { int id = this.id++; return id; } public string NextJob () { return String.Format ("Job #{0}", Id); }
Notes
- This rule is available since Gendarme 2.0
AvoidSmallNamespaceRule
This rule warns when a namespace contains less than five (default) visible types across all assemblies being analyzed (i.e. the assembly set). The rules make special exceptions for:
- specialized namespaces : e.g. *.Design, *.Interop and *.Permissions
- internal namespaces : namespaces without any visible (outside the assemble) types
- small assemblies : that contains a single namespace but less than the minimal number of types (e.g. addins)
- assembly entry point : the namespace of the type being used in an assemble (EXE) entry-point
Bad example:
namespace MyStuff.Special { // single type inside a namespace public class Helper { } }
Good example:
namespace MyStuff { public class Helper { } // ... many other types ... }
AvoidVisibleFieldsRule
This rule checks every type for externally visible fields. Using a property offers much more future freedom to adjust the behavior and validations on a field value without breaking binary compatibility.
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; } }
Notes
- Prior to Gendarme 2.2 this rule was named AvoidPublicInstanceFieldsRule.
AvoidVisibleNestedTypesRule
This rule checks for nested types that are externally visible. Such types are often confused with namespaces which makes them more difficult to document and find by developers. In most cases it is possible to do better without them.
Bad example:
public class Outer { public class Inner { // ... } }
Good example (visibility):
public class Outer { internal class Inner { // ... } }
Good example (unnested):
public class Outer { // ... } public class Inner { // ... }
Notes
- This rule is available since Gendarme 2.0
ConsiderAddingInterfaceRule
This rule checks if a type could declare it implements an interface. Usually, adding the interface in the type declaration will make code more reusable and easier to understand.
Bad example:
public interface IDoable { public void Do (); } public class MyClass { public void Do () { } }
Good example:
public interface IDoable { public void Do (); } public class MyClass : IDoable { public void Do () { } }
ConsiderConvertingFieldToNullableRule
This rule checks for field pairs that are likely trying to provide the same functionality as a single nullable field. If the assembly targets version 2.0, or more recent, of the CLR then the rule will warn about the opportunity to use real nullable fields. The rule will ignore assemblies targetting earlier versions of the CLR.
Bad example:
public class Bad { bool hasFoo; int foo; }
Good example:
public class Good { int? foo; }
Notes
- This rule is available since Gendarme 2.0
ConsiderConvertingMethodToPropertyRule
The rule looks for methods which definition looks quite similar to a property. For example, methods beginning with Is, Get or Set are likely candidates to be promoted into properties.
Bad example:
public class Bad { int foo; public int GetFoo () { return foo; } }
Good example:
public class Good { int foo; public int Foo { get { return foo; } } }
ConsiderUsingStaticTypeRule
This rule check for types that contains only static members and, if the assembly targets the CLR version 2.0 or later, suggest to promote the type to a statictype. The rule will ignore assemblies targeting earlier versions of the CLR.
Bad example:
public class Class { public static void Method () { } }
Good example:
public static class Class { public static void Method () { } }
DeclareEventHandlersCorrectlyRule
The rule inspects all events inside every type and verify if they all have correct signatures.
Bad example:
// the second parameter, inheriting from System.EventArgs, is missing delegate void MyDelegate (int sender); class Bad { public event MyDelegate CustomEvent; }
Good example (delegate):
delegate void MyDelegate (int sender, EventArgs e); class Good { public event MyDelegate CustomEvent; }
Good example (generics):
class Good { public event EventHandler<EventArgs> CustomEvent; }
Notes
- This rule is available since Gendarme 2.2
DisposableTypesShouldHaveFinalizerRule
The rule inspects all types that implements System.IDisposable and contains fields that use native types, like System.IntPtr, System.UIntPtr or System.Runtime.InteropServices.HandleRef. If so the rule will warn unless the type provides a finalizer (destructor in C#).
Bad example:
class NoFinalizer { IntPtr field; }
Good example:
class HasFinalizer { IntPtr field; ~HasFinalizer () { UnmanagedFree (field); } }
DoNotDeclareProtectedMembersInSealedTypeRule
This rule ensure that sealed types (i.e. types that you can't inherit from) do not define family (protected in C#) fields or methods. Such visibility for members would only be useful in sub-types.
Bad example (field):
public sealed class MyClass { protected int someValue; }
Bad example (method):
public sealed class MyClass { protected virtual int GetAnswer () { return 42; } }
Good example (field):
public sealed class MyClass { private int someValue; }
Good example (method):
public sealed class MyClass { public virtual int GetAnswer () { return 42; } }
Notes
- Prior to Gendarme 2.2 this rule applied only to fields and was named DoNotDeclareProtectedFieldsInSealedClassRule
DoNotDeclareVirtualMethodsInSealedTypeRule
This rule ensure that sealed types (i.e. types that you can't inherit from) do not define any new virtual methods. Such methods would only be useful in sub-types. Note that some compilers, like C# and VB.NET compilers, do not allow you to define such methods.
Bad example:
public sealed class MyClass { // note that C# compilers won't allow this to compile public virtual int GetAnswer () { return 42; } }
Good example:
public sealed class MyClass { public int GetAnswer () { return 42; } }
EnsureSymmetryForOverloadedOperatorsRule
This rule checks for operators that are not overloaded in pairs. Some compilers, like the C# compilers, forces you to implement some of the pairs, but other languages might not. The following pairs are checked:
Bad example:
class DoesNotOverloadAdd { public static int operator - (DoesNotOverloadAdd left, DoesNotOverloadAdd right) { return 0; } }
Good example:
class Good { public static int operator + (Good right, Good left) { return 0; } public static int operator - (Good right, Good left) { 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
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 }
FinalizersShouldBeProtectedRule
This rule checks for every finalizers are visible to family only (protected in C#) because otherwise they can be called from the user code. In C# and VB.NET this rule is enforced by the compiler, but some languages (like IL) may not have such a restriction, thus making developer able to declare non-family finalizers.
Bad example (IL):
.class family auto ansi beforefieldinit BadPublicFinalizer extends [mscorlib]System.Object { .method public hidebysig instance void Finalize() cil managed { // ... } }
Good example (C#):
public class GoodProtectedFinalizer { // compiler makes it protected ~GoodProtectedFinalizer () { } }
Good example (IL):
.class family auto ansi beforefieldinit GoodProtectedFinalizer extends [mscorlib]System.Object { .method family hidebysig instance void Finalize() cil managed { // ... } }
FlagsShouldNotDefineAZeroValueRule
This rule ensures that enumerations decorated with the [System.Flags] attribute do not contain a 0 value. This value would not be usable with bitwise operators.
Bad example (using 0 for a normal value):
[Flags] [Serializable] enum Access { Read = 0, Write = 1 }
Bad example (using None):
[Flags] [Serializable] enum Access { // this is less severe since the name of the 0 value helps None = 0, Read = 1, Write = 2 }
Good example:
[Flags] [Serializable] enum Access { Read = 1, Write = 2 }
ImplementEqualsAndGetHashCodeInPairRule
This rule checks for types that either overrides the Equals(object) method without overriding GetHashCode() or overrides GetHashCode without overriding Equals. In order to work correctly types should always override them in pair.
Bad example (missing GetHashCode):
public class MissingGetHashCode { public override bool Equals (object obj) { return this == obj; } }
Bad example (missing Equals):
public class MissingEquals { public override int GetHashCode () { return 42; } }
Good example:
public class Good { public override bool Equals (object obj) { return this == obj; } public override int GetHashCode () { return 42; } }
ImplementICloneableCorrectlyRule
This rule warns every time you implement a object Clone() method without implementing the System.ICloneable interface. Either implement the interface or, if possible, change the return type to the type definition (since can avoid unnecessary casts).
Bad example:
public class MyClass { public object Clone () { MyClass myClass = new MyClass (); return myClass; } }
Good example (ICloneable):
public class MyClass : ICloneable { public object Clone () { MyClass myClass = new MyClass (); return myClass; } }
Good example (not returning object):
public class MyClass { public MyClass Clone () { MyClass myClass = new MyClass (); return myClass; } }
Notes
- Prior to Gendarme 2.2 this rule was named UsingCloneWithoutImplementingICloneableRule
ImplementIComparableCorrectlyRule
This rule checks for types that implements System.IComparable and checks if the type overrides the Equals(object) method and overloads the ==, !=, < and > operators.
Bad example:
public struct Comparable : IComparable { private int x; public int CompareTo (object obj) { return x.CompareTo (((Comparable)obj).x); } }
Good example:
public struct Comparable : IComparable { public int CompareTo (object obj) { return x.CompareTo (((Comparable)obj).x); } public override bool Equals (object obj) { return x == ((Comparable) obj).x; } static public bool operator == (Comparable left, Comparable right) { return (left.x == right.x); } static public bool operator != (Comparable left, Comparable right) { return (left.x != right.x); } static public bool operator > (Comparable left, Comparable right) { return (left.x > right.x); } static public bool operator < (Comparable left, Comparable right) { return (left.x < right.x); } }
Notes
- This rule is available since Gendarme 2.0
InternalNamespacesShouldNotExposeTypesRule
This rule checks for visible types that resides inside internal namespaces, i.e. namespaces ending with Internal or Impl.
Bad example:
namespace MyStuff.Internal { public class Helper { } }
Good example (internal type):
namespace MyStuff.Internal { internal class Helper { } }
Good example (non-internal namespace):
namespace MyStuff { public class Helper { } }
MainShouldNotBePublicRule
This rule is used to warn developer if assembly's entry point, the so-called Mainmethod, 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 example (type is not externally visible):
internal class MainClass { public void Main () { } }
Good example (method is not externally visible):
public class MainClass { internal void Main () { } }
MarkAssemblyWithAssemblyVersionRule
This rule looks at each assembly to see if it contains a [AssemblyVersion]attribute. Early and correct versioning of assemblies is easy and crucial for consumers of your assemblies. Note that when adding the [AssemblyVersion] make sure that it match with the [AssemblyFileVersion] attribute (if existing).
Good example:
[assembly: AssemblyVersion ("1.0.0.0")]
Notes
- This rule is available since Gendarme 2.2
MarkAssemblyWithCLSCompliantRule
This rule looks at each assembly to see if it contains a [CLSCompliant] attribute. CLS compliant assembly can be reused by any CLS-compliant language. It is a good practice to declare your global CLS goal at the assembly level and, if needed, mark some types or members that behave differently inside your assembly.
Good example:
// by default everything in this assembly is CLS compliant [assembly: CLSCompliant (true)]
Notes
- This rule is available since Gendarme 2.2
MarkAssemblyWithComVisibleRule
This rule looks at each assembly to see if it contains a [ComVisible] attribute. Unless the assembly is designed with COM interoperability in mind it is better to declare it entirely as non-COM visible, i.e. [ComVisible (false)].
Good example:
// by default everything in this assembly is not visible to COM consumers [assembly: ComVisible (false)]
Notes
- This rule is available since Gendarme 2.2
MissingAttributeUsageOnCustomAttributeRule
This rule checks that every custom attribute, types that inherit from System.Attribute, should be decorated with an [AttributeUsage] attribute to specify which kind of code members the custom attribute can be applied to.
Bad example:
// this applies to everything - but the meaning is not clear public sealed class SomeAttribute : Attribute { }
Good examples:
// this clearly applies to everything [AttributeUsage (AttributeTargets.All)] public sealed class AttributeApplyingToAnything : Attribute { } // while this applies only to fields [AttributeUsage (AttributeTargets.Field)] public sealed class AttributeApplyingToFields : Attribute { }
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 example (add/substract):
class DoesNotOverloadOperatorEquals { public static int operator + (DoesNotOverloadOperatorEquals a) { return 0; } public static int operator - (DoesNotOverloadOperatorEquals a) { return 0; } }
Bad example (value type):
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 warns when 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 == (OverridesEquals a, OverridesEquals b) { return true; } public override bool Equals (object obj) { OverridesEquals other = (obj as OverridesEquals); if (other == null) { return false; } return (this == other); } }
PreferEventsOverMethodsRule
This rule checks for method names that suggest they are providing similar functionalities to .NET events. When possible the method(s) should be replaced with a real event. In the case that the methods are not using or prroviding events-like features it should be renamed since such names can confuse consumer about what the method is really doing.
Bad example:
public delegate void MouseUpCallback (int x, int y, MouseButtons buttons); public class MouseController { private MouseUpCallback mouse_up_callback; public void RaiseMouseUp (Message msg) { if (mouse_up_callback != null) { mouse_up_callback (msg.X, msg.Y, msg.Buttons); } } public void ProcessMessage (Message msg) { switch (msg.Id) { case MessageId.MouseUp: { RaiseMouseUp (msg); break; } // ... more ... default: break; } } }
Good example:
public class MouseController { public event EventHandler<MessageEvent> MouseUp; public void ProcessMessage (Message msg) { switch (msg.Id) { case MessageId.MouseUp: { EventHandler<MessageEvent> handler = MouseUp; if (handler != null) { handler (new MessageEvent (msg)); } break; } // ... more ... default: break; } } }
PreferIntegerOrStringForIndexersRule
This rule checks for indexer properties that use uncommon types as indexes. Recommanded types includes Int32, Int64 and String. Other types are discouraged since they are generally better served using a method.
Bad example:
public bool this [DateTime date] { get { return false; } }
Good example:
public bool IsSomethingPlanned (DateTime date) { return false; }
Notes
- This rule is available since Gendarme 2.0
ProvideAlternativeNamesForOperatorOverloadsRule
The rule ensure that all overloaded operators are also accessible used named alternatives because 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_Equality : Equals
- 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 + (DoesImplementAdd a, DoesImplementAdd b) { return 0; } public int Add (DoesImplementAdd a) { return this + a; } }
TypesShouldBeInsideNamespacesRule
The rule ensure that all visible types are declared inside a namespace. This helps to avoid potential duplicates when several assemblies are used and is less confusing for consumer of the API.
Bad example:
using System; public class Configuration { }
Good example:
using System; namespace My.Stuff { public class Configuration { } }
TypesWithDisposableFieldsShouldBeDisposableRule
The rule inspects all fields inside a type and looks if any of them is from a type that implements System.IDisposable. If so the rule warns if the type itself doesn't implement System.IDisposable.
Bad examples:
class DoesNotImplementIDisposable { IDisposable field; } class AbstractDispose : IDisposable { IDisposable field; // the field should be disposed in the type that declares it public abstract void Dispose (); }
Good example:
class Dispose : IDisposable { IDisposable field; public void Dispose () { field.Dispose (); } }
TypesWithNativeFieldsShouldBeDisposableRule
The rule inspects all fields inside a type for it's use of specific native types, like IntPtr, UIntPtr and HandleRef. If used the rule warns if the type itself doesn't implement System.IDisposable.
Bad examples:
public class DoesNotImplementIDisposable { IntPtr field; } abstract public class AbstractDispose : IDisposable { IntPtr field; // the field should be disposed in the type that declares it public abstract void Dispose (); }
Good example:
public 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!


