Gendarme's rules about exceptions are located in the Gendarme.Rules.Exceptions.dll assembly. Latest sources are available from anonymous SVN (http://anonsvn.mono-project.com/viewcvs/trunk/mono-tools/gendarme/rules/Gendarme.Rules.Exceptions/).
Table of Contents
1.1 AvoidArgumentExceptionDefaultConstructorRule
1.2 AvoidThrowingBasicExceptionsRule
1.3 DoNotDestroyStackTraceRule
1.4 DoNotSwallowErrorsCatchingNonSpecificExceptionsRule
1.5 DoNotThrowInUnexpectedLocationRule
1.6 DoNotThrowReservedExceptionRule
1.7 ExceptionShouldBeVisibleRule
1.8 InstantiateArgumentExceptionCorrectlyRule
1.9 MissingExceptionConstructorsRule
Rules
AvoidArgumentExceptionDefaultConstructorRule
This rule check that any System.ArgumentException, System.ArgumentNullException, System.ArgumentOutOfRangeException or System.DuplicateWaitObjectException exception created are provided with some useful information about the exception being throw, minimally the parameter name.
Bad example:
public void Add (object key, object value) { if ((obj == null) || (key == null)) { throw new ArgumentNullException (); } Inner.Add (key, value); }
Good example:
public void Add (object key, object value) { if (key == null) { throw new ArgumentNullException ("key"); } if (obj == value) { throw new ArgumentNullException ("value"); } Inner.Add (key, value); }
Notes
- This rule is available since Gendarme 2.0
AvoidThrowingBasicExceptionsRule
This rule check for methods that create basic exceptions like System.Exception, System.ApplicationException or System.SystemException. Those exceptions do not provide enough information about an error condition to be helpful to the consumer of the library.
Bad example:
public void Add (object obj) { if (obj == null) { throw new Exception (); } Inner.Add (obj); }
Good example:
public void Add (object obj) { if (obj == null) { throw new ArgumentNullException ("obj"); } Inner.Add (obj); }
Notes
- This rule is available since Gendarme 2.0
DoNotDestroyStackTraceRule
This rule check method's catch block to see if they are throwing back the caught exception. Doing so would destroy the stack trace of the original exception. If you need to (re-)throw the exception caught by the catch block, you should use throw;instead of throw ex;.
Bad example:
try { Int32.Parse ("Broken!"); } catch (Exception ex) { Assert.IsNotNull (ex); throw ex; }
Good example:
try { Int32.Parse ("Broken!"); } catch (Exception ex) { Assert.IsNotNull (ex); throw; }
Notes
- Prior to Gendarme 2.0 this rule was named DontDestroyStackTraceRule.
DoNotSwallowErrorsCatchingNonSpecificExceptionsRule
This rule is used for ensure that methods do not swallow the catched exceptions. If you decide catch a non-specific exception, you should take care, because you wont know exactly what went wrong. You should catch exceptions when you know why an exception can be thrown, and you can take a decision based on the failure.
Bad example:
try { File.Open ("foo.txt", FileMode.Open); } catch (Exception) { //Ooops what's failed ??? UnauthorizedException, FileNotFoundException ??? }
Good example (catch a specific exception):
try { File.Open ("foo.txt", FileMode.Open); } catch (FileNotFoundException exception) { //I know that the system can't find the file. }
Good example (catch all and rethrow):
try { File.Open ("foo.txt", FileMode.Open); } catch { Console.WriteLine ("An error has happened."); throw; // You don't swallow the error, because you rethrow the original exception. }
Notes
- Prior to Gendarme 2.0 this rule was named DontSwallowErrorsCatchingNonspecificExceptionsRule.
DoNotThrowInUnexpectedLocationRule
There are a number of methods which have constraints on the exceptions which they may throw. This rule checks the following methods:
- Property getters - properties should work very much like fields: they should execute very quickly and, in general, should not throw exceptions. However they may throw System.InvalidOperationException, System.NotSupportedException, or an exception derived from these. Indexed getters may also throw System.ArgumentException or System.Collections.Generic.KeyNotFoundException.
- Event accessors - in general events should not throw when adding or removing a handler. However they may throw System.InvalidOperationException, System.NotSupportedException, System.ArgumentException, or an exception derived from these.
- Object.Equals and IEqualityComparer<T>.Equals - should not throw. In particular they should do something sensible when passed null arguments or unexpected types.
- Object.GetHashCode - should not throw or the object will not work properly with dictionaries and hash sets.
- IEqualityComparer<T>.GetHashCode - may throw System.ArgumentException.
- Object.ToString - these are called by the debugger to display objects and are also often used with printf style debugging so they should not change the object's state and should not throw.
- static constructors - should very rarely throw. If they do throw then the type will not be useable within that application domain.
- finalizers - should not throw. If they do (as of .NET 2.0) the process will be torn down.
- IDisposable.Dispose - should not throw. If they do it's much harder to guarantee that objects clean up properly.
- Dispose (bool) - should not throw because that makes it very difficult to clean up objects and because they are often called from a finalizer.
- operator== and operator!= - should not throw. In particular they should do something sensible when passed null arguments or unexpected types.
- implicit cast operators - should not throw. These methods are called implicitly so it tends to be quite surprising if they throw exceptions.
Note that the rule does not complain if a method throws System.NotImplementedException because DoNotForgetNotImplementedMethodsRule will flag them. Also the rule may fire with anonymous types with gmcs versions prior to 2.2, see [1] (https://bugzilla.novell.com/show_bug.cgi?id=462622) for more details.
Bad example:
public override bool Equals (object obj) { if (obj == null) { return false; } Customer rhs = (Customer) obj; // throws if obj is not a Customer return name == rhs.name; }
Good example:
public override bool Equals (object obj) { Customer rhs = obj as Customer; if (rhs == null) { return false; } return name == rhs.name; }
Notes
- This rule is available since Gendarme 2.4
DoNotThrowReservedExceptionRule
This rule check for methods that create reserved exceptions like System.ExecutionEngineException, System.IndexOutOfRangeException, NullReferenceException or System.OutOfMemoryException. Those exceptions should only be thrown by the .NET runtime.
Bad example:
public void Add (object obj) { if (obj == null) { throw new NullReferenceException ("obj"); } Inner.Add (obj); }
Good example:
public void Add (object obj) { if (obj == null) { throw new ArgumentNullException ("obj"); } Inner.Add (obj); }
Notes
- This rule is available since Gendarme 2.0
ExceptionShouldBeVisibleRule
This rule check for non visible exception types that derive directly from the most basic exceptions: System.Exception, System.ApplicationExceptionor System.SystemException. Those basic exceptions, being visible, will be the only information available to the API consumer - but do not contain enough data to be useful.
Bad example:
internal class GeneralException : Exception { }
Good example (visibility):
public class GeneralException : Exception { }
Good example (base class):
internal class GeneralException : ArgumentException { }
Notes
- This rule is available since Gendarme 2.0
InstantiateArgumentExceptionCorrectlyRule
This rule check that any System.ArgumentException, System.ArgumentNullException, System.ArgumentOutOfRangeException or System.DuplicateWaitObjectException exception created to ensure the order of their parameters, in particular the position of parameterName, is correct. This is a common mistake since the position is not consistent across all exceptions.
Bad example:
public void Show (string s) { if (s == null) { throw new ArgumentNullException ("string is null", "s"); } if (s.Length == 0) { return new ArgumentException ("s", "string is empty"); } Console.WriteLine (s); }
Good example:
public void Show (string s) { if (s == null) { throw new ArgumentNullException ("s", "string is null"); } if (s.Length == 0) { return new ArgumentException ("string is empty", "s"); } Console.WriteLine (s); }
Notes
- This rule is available since Gendarme 2.2
MissingExceptionConstructorsRule
This rule check that any exceptions, i.e. types deriving from System.Exception, provide all the necessary constructors that can be expected from consumer or required by the runtime.
Bad example:
public class GeneralException : Exception { // it should be a default public constructor private GeneralException () { } }
Good example:
public class GeneralException : Exception { public GeneralException () { } public GeneralException (string message) { } public GeneralException (string message, Exception inner) { } protected GeneralException (SerializationInfo info, StreamingContext context) { } }
Notes
- This rule is available since Gendarme 2.0
Feedback
Please report any documentation errors, typos or suggestions to the Gendarme Google Group (http://groups.google.com/group/gendarme). Thanks!


