Question

When I start writing a method, I usually check for exceptional conditions first in the method, using If-Then-Throw blocks.

public void ReadFile(string filePath)
{
    if (string.IsNullOrEmpty(filePath)
    {
        throw new ArgumentException(...

This style seems to be very clear and easy to understand, but it takes up more space than I think is necessary. I want to be able to handle errors and exceptional conditions in a smart way that enables whoever's reading these errors to easy take care of them while also keeping the code itself clean.

I've looked a bit at Code Contracts, which seems to me a requirement for certain conditions before and after a method's execution. That seems to be a tad bit overkill for just a null string, and I'm not sure if you can have contract clauses within the method itself, for instance, if the path is not null but no file exists at that path.

The solution I'm thinking of using is rolling my own Assert class. This class will basically turn the above If-Then-Throw into a simple one liner.

Assert.IsFalse<ArgumentException>(string.IsNullOrEmpty(filePath), "The path cannot be null or empty.");

All Assert methods would throw an exception using the exception type and the message in the last argument. The thing is that I'm not sure if this is good practice. Does it confuse what exceptions are truly for, or what Assert actually means? Would it make error-handling easier or harder?

Was it helpful?

Solution 2

To be honest, I'm not sure a custom Assert class would help clarify anything, and I'm not sure you should be worried about two lines need to check and throw an exception vs one line. Your current way of checking parameters is the way we do things as well. In fact, a majority of public methods around our code look something like this:

public void PerformStringOperation(string str1, string str2)
{
    if(string.IsNullOrEmpty(string1))
        throw new ArgumentNullException(...);
    if(string.IsNullOrEmpty(string2))
        throw new ArgumentNullException(...);

   // perform string operation(s) here
}

We have never found it too encumbering, and I'm sure it is the exact solution used by many teams.

OTHER TIPS

I would say this is not good practice. As you pointed out, this would confuse the roles of Assertions and Exceptions. The topic is somewhat common, this link has a lot of nice ideas. By combining exceptions and assertions, you end up with a conundrum... is the class an exception helper, or is it an assertion helper?

Since assertions are compiled out of the Release build, would your assertion class even work in Release mode? It would be non-conventional to expect an Assertion class to work in release mode. So, would your Assertion class throw the exceptions in Release mode? There lies the confusion. By convention, I would say the exception should not be thrown when using an Assert Class (in Release mode) because it is understood that assertions are not part of a Release build.

The code above should not make 'Exception Handling' easier nor harder, it should be the same since the exception handling depends on what is catching the exception in the stack. I think you are really asking if it makes throwing Exceptions easier or harder. I think it could make dealing with your exceptions easier. I also think it is probably unnecessary. What is most important is that you are consistent with this... if you are going to use an ExceptionHelper class, then embrace it and be consistent... otherwise it is all done for naught.

Debug.Assert:

  • Use liberally
  • Use whenever there is a chance that an assumption could be wrong
  • Used to help other programmers, not necessarily the end user
  • Should never affect the flow of the program
  • Not compiled in Release builds
  • Always yells 'BLOODY MURDER' when something unexpected happens, this is a good thing
  • many other reasons, I'm not aiming for a complete list

Exceptions:

  • Can be caused for any reason, it is not always known why
  • Always in debug or release builds
  • Pertains to how the application flows
  • Some exception handlers may silently swallow an exception and you would never know it
  • many other reasons, I'm not aiming for a complete list
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top