Validate arguments of public methods
| TypeName | ValidateArgumentsOfPublicMethods |
| CheckId | CA1062 |
| Category | Microsoft.Design |
| Breaking Change | NonBreaking |
All reference arguments passed to externally visible methods should be checked against null. If appropriate, throw a System.ArgumentNullException when the argument is null.
The following example shows a method that violates the rule and a method that satisfies the rule.
using System; namespace DesignLibrary { public class Test { // This method violates the rule. public void DoNotValidate(string input) { if( input.Length != 0 ) { Console.WriteLine(input); } } // This method satisfies the rule. public void Validate(string input) { if( input == null ) { throw new ArgumentNullException("input"); } if( input.Length != 0 ) { Console.WriteLine(input); } } } }
In Visual Studio 2005, this rule has a number of limitations. One limitations is that
it does not detect that parameters are being passed to another method that does the validation.
Another limitation is that it does not understand short circuit operators.
Care must be taken when overloading the equality (==) operator. In this case, a standard comparison of either object being passed to the overloaded operator with null, ie.
if (object == null) ...
will cause an infinite loop to be created at run-time and an overflow exception will be thrown whenever the method is called. To avoid this whilst not upsetting FxCop, use ReferenceEquals to compare the two items for reference equality first, then to compare each operand with null, returning true when both operands are null and false when only one operand is null. Finally perform the comparison of properties that determines whether the two parameters are functionality equal.
This example comes from the BusinessObject base class of my business framework. The Reference property is used to determine euality of two business objects. Note that the first check for reference equality correctly identifies if both items are null meaning my earlier revision to this comment was unnecessary:
[C#]
/// <summary>
/// Compares two business objects for equality.
/// </summary>
/// <param name="object1">The first business object.</param>
/// <param name="object2">The second business object.</param>
/// <returns>True if the business objects are the same.</returns>
public static bool operator ==(BusinessObject object1, BusinessObject object2)
{
if (Object.ReferenceEquals(object1, object2)) return true;
if (Object.ReferenceEquals(object1, null)) return false;
if (Object.ReferenceEquals(object2, null)) return false;
return object1.Reference == object2.Reference;
}
/// <summary>
/// Compares two business objects for inequality.
/// </summary>
/// <param name="object1">The first business object.</param>
/// <param name="object2">The second business object.</param>
/// <returns>True if the business objects are different.</returns>
public static bool operator !=(BusinessObject object1, BusinessObject object2)
{
// Validate
if (Object.ReferenceEquals(object1, object2)) return false;
if (Object.ReferenceEquals(object1, null)) return true;
if (Object.ReferenceEquals(object2, null)) return true;
return object1.Reference != object2.Reference;
}
As the equality operator is overloaded, so should be the Equals method and the GetHashCode method. In the Equals method there is no requirement to compare null against null as the current object cannot be null.
[C#]
/// <summary>
/// Compares the business object with a second business object.
/// </summary>
/// <param name="obj">The business object to compare with.</param>
/// <returns>True if the business objects are the same.</returns>
public override bool Equals(object obj)
{
// Validate
if (obj == null) return false;
return _reference == ((BusinessObject)obj).Reference;
}
/// <summary>
/// Generates a hash code for the business object;
/// </summary>
/// <returns></returns>
public override int GetHashCode()
{
return _reference.GetHashCode();
}
In Visual Studio 2005, this rule has a number of limitations:
1. It does not detect that parameters are being passed to another method that does the validation:
[C#]public string Method(string value)
{
EnsureNotNull(value);
// Fires incorrectly
return value.ToString();
}private void EnsureNotNull(string value)
{
if (value == null)
throw new ArgumentNullException("value");
}[Visual Basic]Public Function Method(value as String) As String)
EnsureNotNull(value)' Fires incorrectly
Return value.ToString()
End Function
Private Sub EnsureNotNull(value as String)
If value Is Nothing Then
Throw New ArgumentNullException("value")
End Sub
2. It does not understand short circuit operators:
[C#]
public string Method(string value1, string value2)
{
if (value1 == null || value2 == null)
throw new ArgumentNullException(value1 == null ? "value1" : "value2");
// Fires incorrectly
return value1.ToString() + value2.ToString();
}
[Visual Basic]Public Function Method(value1 as String, value2 as String) As String
If value1 Is Nothing OrElse value2 Is Nothing Then
Throw New ArgumentNullException()
End If
' Fires incorrectly
Return value1.ToString() + value2.ToString()
End Function
If you encounter these situations, simply suppress the warning.
- 6/16/2007
- David M. Kean
- 6/16/2007
- David M. Kean