So far I've learned that (usually) when you assert, you should also throw. At first I wasn't sure it was right, it just made sense1, and then this answer verified.
The problem I have is that it causes repeated-code (at least via contracts). Here's an example of a name field that can't be null or white-space:
public String Name
{
get { return _name; }
set
{
Contract.Requires(String.IsNullOrWhiteSpace(value) == false, "Names cannot be null or whitespace.");
if (String.IsNullOrWhiteSpace(value))
throw new ArgumentException("Names cannot be null or whitespace.");
_name = value;
}
}
Clearly both the condition, and the error message are repeated. How should I handle it? In one property it's manageable but in a class with multiple fields it's littering.
Additional Information
I thought of using Contract.Requires<TException>
(which would assert in debug and throw in release), but the condition (which is the code) would be the message of the exception, which would most likely be displayed to the user (a user would probably like to know why his program crashed, and I wouldn't want to show the actual code). Here's an example:
static void MyFunction(Boolean youCanSeeMyCode = false)
{
Contract.Requires<Exception>(youCanSeeMyCode, "(This is the exception's message)");
}
...
try
{
MyFunction();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error");
}
Any suggestions? I'm at a loss.
1 It made sense because if you only use assert and you still have a bug somewhere that you're unaware of, the release build would carry on as if everything's okay and hell could break loose.