I use parameter objects to encapsulate the parameters that are passed to my business rules. The rule is created using a context parameter, which may then be modified, then at a later time the rule is executed. Some of the properties of this object are required, otherwise the method would throw a NullReferenceException
. However, if I throw an ArgumentNullException
, I get a warning saying that the parameter name does not match one of my parameters. What would be the appropriate exception for this situation?
public class GetAttributes : BusinessRuleBase
{
private readonly IGetAttributesContext _context;
public GetAttributes(IGetAttributesContext context)
{
_context = context;
}
public override void Execute()
{
if (_context.AttributeModel == null)
{
//Exception would be thrown here
}
_context.Attributes = _context.AttributeModel
.DoSomething(_context.EntityType);
}
}
If you are using Code Contracts and you are willing to publicly expose a HasAttributeModel
property, I recommend
Contract.Requires(this.HasAttributeModel);
Otherwise, you should throw a custom exception that derives from InvalidOperationException
here. The method that you are trying to execute is not valid given the object's current state. From the documentation:
The exception that is thrown when a method call is invalid for the object's current state.
Your custom message should say that the instance's AttributeModel
is null
.
The larger question is, why are you allowing your instances to be in a state where a method could be invoked on them while the object is in an invalid state? You should avoid this, if you can. For example, why isn't GetAttributes
checking that context.AttributeModel
is not null
? You could have
Contract.Requires(context.AttributeModel != null);
as a precondition for this method. However, there is some danger here in that if someone retains a live reference to the referrent of the parameter context
, they could destroy the state since you maintain a reference via the private variable _context
. Be aware of this, and avoid it if you can.