I have an insert query that returns an int. Based on that int I may wish to throw an exception. Is this appropriate to do within a switch statement?
switch (result)
{
case D_USER_NOT_FOUND:
throw new ClientException(string.Format("D User Name: {0} , was not found.", dTbx.Text));
case C_USER_NOT_FOUND:
throw new ClientException(string.Format("C User Name: {0} , was not found.", cTbx.Text));
case D_USER_ALREADY_MAPPED:
throw new ClientException(string.Format("D User Name: {0} , is already mapped.", dTbx.Text));
case C_USER_ALREADY_MAPPED:
throw new ClientException(string.Format("C User Name: {0} , is already mapped.", cTbx.Text));
default:
break;
}
I normally add break statements to switches but they will not be hit. Is this a bad design? Please share any opinions/suggestions with me.
Thanks,
~ck in San Diego
Why not?
From The C# Programming Language, Third Ed. by Anders Hejlsberg et al, page 362:
The statement list of a switch section typically ends in a break, goto case, or goto default statement, but any construct that renders the end point of the statement list unreachable is permitted. [...] Likewise, a throw or return statement always transfers control elsewhere and never reaches its end point. Thus the following example is valid:
switch(i) {
case 0:
while(true) F();
case 1:
throw new ArgumentException();
case 2:
return;
}
No problem... why would this be bad design?
Alternatively, since the exception type is the same in all cases, you could construct a lookup table for the error messages. That would save you some code duplication. For example:
static private Dictionary<int, string> errorMessages;
static
{
// create and fill the Dictionary
}
// meanwhile, elsewhere in the code...
if (result is not ok) {
throw new ClientException(string.Format(errorMessages[result], cTbx.Text, dTbx.Text));
}
In the messages themselves, you can select the appropriate parameter with {0}, {1}, etc.
I don't really agree with your variable naming conventions ;), but I don't see why what you did would be inappropriate. It seems like a fairly elegant way of translating an error from one medium to another.
I'm assuming that your "insert query" is some form of stored proc.
If possible it would probably be better if you threw wherever the failed result is set, otherwise you end up with having to do both result checking and throwing. But might not be possible of course.
Also, I'd make your error strings into resources or constants with placeholders so that you don't have to change multiple places if you want to change the wording.
I think this is OK. It seems like you are mapping an return code to an exception, using a switch statement. As long as there are not too many cases, this is not a problem.
I don't see any issue with using a switch in your case.
The stronger consideration should go to whether exceptions themselves are appropriate. Generally, exceptions should be used only when a situation arises that is outside the bounds of expected behavior. Exceptions shouldn't be used as program flow logic. In your case you're probably okay to use them based on the code I see.
There is nothing wrong with the approach you are taking. Switch statements are a lot easier to read than if/then statements (and potentially faster too). The other thing you could do is load the possible exceptions in a
Dictionary<Result_Type, Exception>
and pull the exception from there. If you have lots of switch statements this would make the code more compact (and you can add and remove them at runtime if you need to).
Maybe I beg to differ from all the answers here..
Instead of having to switch in the code, I would rather pass in the result to the ClientException class & let it decide what string it needs to show rather then have an ugly switch all over the place to create various messages
My code would look like:
throw new ClientException(result, cTbx.Text);
So, even if you can throw errors in switch...case, you can avoid it all is my take
Related
I want to add column from one table to another.
Here, colName is string variable, which is extracted from hard-coded parameter provided by developer.
so chances of colName being incorrect is very less.
I want to avoid exception raised due to wrong colName.
Which is the best way to achieve same?
I thought of two options below.
if(_table.Columns.Contains(colName))
{
AddColumnToTable(_table.Columns[colName]);
}
OR
try
{
AddColumnToTable(_table.Columns[colName]);
}
catch { }
First of all, the whole world died a little inside when this happened:
catch { }
But I digress...
The real question isn't whether you should use if vs. try, the real question is:
If the column can't be added, then what?
If this is an expected scenario and basically "not a big deal" and the logic can continue just fine without adding the column, then if is definitely the way to go. As mentioned in a comment on the question, "test and then act".
If, however, this is not an expected scenario and it "is a big deal" and the logic can't meaningfully continue, throw an exception. Don't catch it and ignore it. Let the consuming code (at the application level) catch it and handle it, likely notifying a user or logging the error or perhaps even attempting to correct it in some way.
(Or if this code is at the application level, catch it here and handle it. The point being that handling is different from catching. The latter is a simple catch block, the former is the custom logic required to respond to the error in a meaningful way.)
You can even add further information to the exception. For example:
try
{
// perform some operation
}
catch (SpecificException ex)
{
throw new CustomException("Failed to perform Operation X in the context of Y.", ex);
}
This can be very valuable when diagnosing a production system where you can't attach a debugger. Specific exception types, helpful error messages, and of course the technical details of the original exception are all necessary tools.
Based solely on the information you provide there is only one conclusion :
if(_table.Columns.Contains(colName))
{
AddColumnToTable(_table.Columns[colName]);
}
because the alternative is an exception handling with an empty catch block. This basically means that it really IS your intent not to do anything with the condition that the colName is not found.
However if your code is stripped down to an arbitrary example and you just cleared the catch block to make the post more condense, the conclusion might be different.
Doing this :
catch { }
Should anyhow be avoided.
Based on this statement :
Here, colName is string variable, which is extracted from hard-coded parameter provided by developer.
You could opt to include an assertion in your code instead of an exception because passing the wrong column name can be considered an application bug.
Because you don't really want to foresee an exception I think an assert is quite a good alternative. That would yield following code :
if(_table.Columns.Contains(colName))
{
AddColumnToTable(_table.Columns[colName]);
}
else Debug.Assert(false,"Column name is wrong, please correct calling code.");
or more condense :
Debug.Assert(_table.Columns.Contains(colName),
"Column name is wrong, please correct calling code.");
AddColumnToTable(_table.Columns[colName]);
Never use try/catch if you can use if. It's the matter of code readability and maintainability.
If you value performance, however, you might consider possibility of failure in this scenario. Your library might do something like this:
void AddColumn(string columnName, Column column)
{
if(this.Columns.Contains(columnName))
throw new DuplicateColumnException();
else
this.Columns.Add(columnName, column);
}
Which would mean that your if would add second Contains invocation and depending on its complexity throwing an exception might be better than invoking second check.
The best way to resolve this would be finding the method that sets the column:
void SetColumn(string columnName, Column column)
{
if(this.Columns.Contains(columnName))
this.Columns[columnName] = column;
this.Columns.Add(columnName, column);
}
or simply:
void SetColumn(string columnName, Column column)
{
this.Columns[columnName] = column;
}
In the past I have written games in which performance is incredibly important. I found that in cases where the "catch" statement was being hit, there was a serious performance impact. Things were really slow. i guess this is because it has to capture all details about what went wrong and try and output that in the catch statement, all very inefficient stuff. I would try and avoid using a try statement wherever you can. It is always best to do an if statement to capture this sort of thing, especially if performance is important.
I've come across a scenario that I'm not too sure how to approach.
We're trying to get our unit tests code coverage to 100%.
I've been trying to take a TDD approach to development, writing tests, making it pass, writing a failing test, adding more code to make it pass, etc.
While doing this I found that I wrote a class like this:
public enum IntervalType : int
{
Shift = 1,
PaidBreak = 2,
UnpaidBreak = 3
}
public static class QuarterFactory
{
public static IQuarter CreateQuarter(IntervalType intervalType)
{
switch (intervalType)
{
case IntervalType.Shift:
return new ShiftQuarter();
default:
throw new ArgumentException(String.Format("Unable to create a Quarter based on an IntervalType of: {0}", intervalType));
}
}
}
As coding progressed the factory expanded to this:
public static class QuarterFactory
{
public static IQuarter CreateQuarter(IntervalType intervalType)
{
switch (intervalType)
{
case IntervalType.Shift:
return new ShiftQuarter();
case IntervalType.PaidBreak:
return new PaidBreakQuarter();
case IntervalType.UnpaidBreak:
return new UnpaidBreakQuarter();
default:
throw new ArgumentException(String.Format("Unable to create a Quarter based on an IntervalType of: {0}", intervalType));
}
}
}
The first question I'm asking is:
Now that the factory fulfills the enum, do I remove the default exception for the sake of code coverage, or do I keep the exception in there as the default in the event that someone adds a new type to the enum and forgets to modify the factory?
The second question I'm asking is:
If I decided to remove the exception and default the type to be UnpaidBreakQuarter - does it make sense to default the IQuarter returned to UnpaidBreakQuarter, or would this raise the question of "why is the default the UnpaidBreakQuarter, is there a business rule for this?".
Regards,
James
You can still get 100% code coverage. Consider the following line that compiles just fine:
QuarterFactory.CreateQuarter((IntervalType)0);
Thus, this answers the second question as well. You can get really confusing results if that would return an UnpaidBreakQuarter.
So in short:
Keep the default, unit test that it throws exception if passing
something unexpected (like the line above)
Don't do it. If someone did not specify that they wanted this,
they wouldn't expect it to be returned
You can even get the exception to be raised by doing this:
QuarterFactory.CreateQuarter(0);
I think you should keep the default block, it's a good practice, especially for the case you already mentioned, that is if someone would modify the code in the future adding a new IntervalType.
The answer to the second question comes consequently :) Btw, using the default for a specified value because "I know that the only value left is that" is really horrible, the default value was intended exactly for exceptions or unexpected cases, or at most for the most general ones (i.e: the first not, the second not, ok, so ANY other case should be this value).
I think you should keep the default at the expense of your 100% code coverage, unless there really is a business rule for this and it has been documented. If you choose to keep it, when someone adds another value in the enum, an exception will be thrown as a "reminder" to add the case in the switch statement, which I bet is good.
You know that this sort of switch/enum combo is generally a code smell right?
http://c2.com/cgi/wiki?SwitchStatementsSmell
You could refactor to use polymorphism: that would keep your 100% coverage, allow easy addition of new cases, and not need a default because the compiler would prevent it.
The two most common refactorings in this case are "Replace Type Code with Class" and the more specific "Replace Type Code with Strategy". Also "Replace Conditional with Polymorphism" is of course worth a look.
http://refactoring.com/catalog/replaceConditionalWithPolymorphism.html
Surely the compiler knows that it's the last label of the switch statement?
Having a break after your switch's final case statement is good defensive programming. If, perhaps in the future, another case statement is added below, it removes the risk of the program's flow falling through from the case above.
It's because in C++ this is what happens:
switch(a)
{
case 1:
// do stuff
case 2:
// do other stuff
}
If a is 1, then - according to C++ rules - both "do stuff" and "do other stuff" would happen. So that C++ programmers coming to C# do not get tripped up (and to make code clearer all 'round), C# requires that you explicitly specify whether you want to break or fall through to a different label.
Now, as for why you need the break on the last block, that's a simple matter of consistency. It also make re factoring easier: if you move the cases around, you don't suddenly end up with errors because of a missing break statement. Also, what happens when you want to add another label, etc, etc.
Consistency. Same reason as being able to have a comma after the last enum definition or the last assignment in an object instantiation statement with braces. And the last case might not always be the last case.
It also makes it so there are fewer special cases.
And if that's the case, then it is easier to learn, write, or read. Although that adds to the consistency thing.
In C# switch statements you must explicitly state to break or goto another case or goto default.
In C and C++, switch statements have fall through labels without a break. Having the user explicitly say what they want to do is important in C# to avoid bugs. A lot of users come to C# from C++ for example.
About the last case statement in particular that you're asking about. I can think of 3 good reasons.
It's important to keep things consistent in any language.
What if you append another case after it later on, what should be done with default?
Why should break be the default? Why not goto? There is ambiguity here.
According to http://msdn.microsoft.com/en-us/library/06tc147t.aspx
You cannot "fall through" any switch section, including the last one.
Fall through can be avoided by any of the following: break, goto, or return.
Actually There is one case when you don't have to put break
Consider this code:
using System;
public class Program
{
public static void DoStuff()
{
}
public static void DoAnotherStuff()
{
}
public static void Main()
{
switch(1)
{
case 1: DoStuff(); break;
default: DoAnotherStuff();
}
}
}
Using C# 4.0 compiler it only gives you a nice CS0162: Unreachable code warning
It appears that since switch has a constant expression the compiler already knows wich path it's going to execute, then just ignores the dafault label.
The cool thing is that if you change switch(1) to switch(2) it no longer compiles because the default label lacks its break.
Edit: From the C# Reference
The requirement in C# is that the end of every switch section, including the final one, is unreachable. Although this requirement usually is met by using a jump statement, the following case also is valid, because the end of the statement list cannot be reached.
case 4:
while (true)
Console.WriteLine("Endless looping. . . .");
That explains why the default does not need a break. In fact any unreacheable label doesn't need a break nor return nor goto
When using a switch, to break is not the only option. You also have the option of going to another case, going to the default case, going to another label, or returning. It is also possible to have multiple cases that have a single implementation body. Since there are up to five options plus the ability to have multiple cases for one implementation, the compiler is not able to simply put in the "correct" answer.
You have to choose what you intend to do. It ensures the compiler does the right thing, makes your code clearer, and makes it more difficult to do dumb-programmer-things, like add another case after the "last one", and forget to put in a break/goto/return.
According to this blog post by Eric Lippert (Case 2), it allows you to be able to arbitrarily re-order your switch sections without accidentally introducing a breaking change:
It [the compiler] requires that every switch section,
including the last one, have an
unreachable end point. The purpose of
this rule, and of the no-fall-through
rule in general, is that we want you
to be able to arbitrarily re-order
your switch sections without
accidentally introducing a breaking
change.
As mentioned, you can use default:, but consider case null too. case null: does need a break;
case null:
iEvaluatedToNothing();
break;
If you want to "waterfall" down you can do something like this;
switch (deliverMail)
{
case null:
case "":
case "Address0":
deliverMail0();
goto case "1";
case "1":
deliverMail1();
break;
}
You can use this with breaks as needed, but one is required on the last evaluation.
Let's say we have a function that changes a password for a user in a system in an MVC app.:
public JsonResult ChangePassword
(string username, string currentPassword, string newPassword)
{
switch (this.membershipService.ValidateLogin(username, currentPassword))
{
case UserValidationResult.BasUsername:
case UserValidationResult.BadPassword:
// abort: return JsonResult with localized error message
// for invalid username/pass combo.
case UserValidationResult.TrialExpired
// abort: return JsonResult with localized error message
// that user cannot login because their trial period has expired
case UserValidationResult.Success:
break;
}
// NOW change password now that user is validated
}
membershipService.ValidateLogin() returns a UserValidationResult enum that is defined as:
enum UserValidationResult
{
BadUsername,
BadPassword,
TrialExpired,
Success
}
Being a defensive programmer, I would change the above ChangePassword() method to throw an exception if there's an unrecognized UserValidationResult value back from ValidateLogin():
public JsonResult ChangePassword
(string username, string currentPassword, string newPassword)
{
switch (this.membershipService.ValidateLogin(username, currentPassword))
{
case UserValidationResult.BasUsername:
case UserValidationResult.BadPassword:
// abort: return JsonResult with localized error message
// for invalid username/pass combo.
case UserValidationResult.TrialExpired
// abort: return JsonResult with localized error message
// that user cannot login because their trial period has expired
case UserValidationResult.Success:
break;
default:
throw new NotImplementedException
("Unrecognized UserValidationResult value.");
// or NotSupportedException()
break;
}
// Change password now that user is validated
}
I always considered a pattern like the last snippet above a best practice. For example, what if one developer gets a requirement that now when users try to login, if for this-or-that business reason, they're suppose to contact the business first? So UserValidationResult's definition is updated to be:
enum UserValidationResult
{
BadUsername,
BadPassword,
TrialExpired,
ContactUs,
Success
}
The developer changes the body of the ValidateLogin() method to return the new enum value (UserValidationResult.ContactUs) when applicable, but forgets to update ChangePassword(). Without the exception in the switch, the user is still allowed to change their password when their login attempt shouldn't even be validated in the first place!
Is it just me, or is this default: throw new Exception() a good idea? I saw it some years ago and always (after groking it) assume it to be a best practice.
I always throw an exception in this case. Consider using InvalidEnumArgumentException, which gives richer information in this situation.
With what you have it is fine although the break statement after it will never be hit because execution of that thread will cease when an exception is thrown and unhandled.
I always like to do exactly what you have, although I usually throw an ArgumentException if it's an argument that was passed in, but I kind of like NotImplementedException better since the error is likely that a new case statement should be added rather than the caller should change the argument to a supported one.
I've used this practice before for specific instances when the enumeration lives "far" from it's use, but in cases where the enumeration is really close and dedicated to specific feature it seems like a little bit much.
In all likelihood, I suspect an debug assertion failure is probably more appropriate.
http://msdn.microsoft.com/en-us/library/6z60kt1f.aspx
Note the second code sample...
I think approaches like this can be very useful (for example, see Erroneously empty code paths). It's even better if you can have that default-throw be compiled away in released code, like an assert. That way you have the extra defensiveness during development and testing, but don't incur the extra code overhead when releasing.
You do state that you're being very defensive and I might almost say this is overboard. Isn't the other developer going to test their code? Surely, when they do the simplest of tests they'll see that the user can still log in - so, then they'll realize what they need to fix. What you're doing isn't horrible or wrong, but if you're spending a lot of your time doing it, it might just be too much.
For a web application I would prefer a default that generates a result with an error message that asks the user to contact an adminstrator and logs an error rather than throws an exception that might result in something less meaningful to the user. Since I can anticipate, in this case, that the return value might be something other than what I expect I would not consider this truly exceptional behavior.
Also, your use case that results in the additional enum value shouldn't introduce an error into your particular method. My expectation would be that the use case only applies on login -- which would happen before the ChangePassword method could legally be called, presumably, since you'd want to make sure that the person was logged in before changing their password -- you should never actually see the ContactUs value as a return from the password validation. The use case would specify that if a ContactUs result is return, that authentication fails until the condition resulting in the result is cleared. If it were otherwise, I'd expect that you'd have requirements for how other parts of the system should react under that condition and you'd write tests that would force you to change the code in this method to conform to those tests and address the new return value.
Validating runtime constraints is usually a good thing, so yes, best practice, helps with 'fail fast' principle and you are halting (or logging) when detecting an error condition rather than continuing silently. There are cases where that is not true, but given switch statements I suspect we do not see them very often.
To elaborate, switch statements can always be replaced by if/else blocks. Looking at it from this perspective, we see the throw vs do not throw in a default switch case is about equivalent to this example:
if( i == 0 ) {
} else { // i > 0
}
vs
if( i == 0 ) {
} else if ( i > 0 ) {
} else {
// i < 0 is now an enforced error
throw new Illegal(...)
}
The second example is usually considered better since you get a failure when an error constraint is violated rather than continuing under a potentially incorrect assumption.
If instead we want:
if( i == 0 ) {
} else { // i != 0
// we can handle both positve or negative, just not zero
}
Then, I suspect in practice that last case will likely appear as an if/else statement. Because of that the switch statement so often resembles the second if/else block, that the throws is usually a best practice.
A few more considerations are worthwhile:
- consider a polymorphic approach or an enum method to replace the switch statement altogether, eg: Methods inside enum in C#
- if throwing is the best, as noted in other answers prefer to use a specific exception type to avoid boiler plate code, eg: InvalidEnumArgumentException
I never add a break after a throw statement contained in a switch statement. Not the least of the concerns is the annoying "unreachable code detected" warning. So yes, it is a good idea.
Which exception should I use when the program reaches a logic state that I "know" won't happen, and if it does, something is terribly bad?
For example:
int SomeFunction(int arg) {
SomeEnum x = Whatever(arg, somePrivateMember);
switch (x) {
case SomeEnum.Value1:
return SomeFunction1();
case SomeEnum.Value1:
return SomeFunction2();
default:
throw new WhatTypeToThrow();
}
}
Clearly, ArgumentException is a long-shot here since the invalid value for x could have come from a bug in Whatever(), or an invalid combination of any arguments and/or the current instance state.
I'm looking for something such as an InvalidProgramStateException, InternalErrorException or similar.
Of course I could define my own, but I wonder if there is a suitable exception in the framework.
Edit: Removed the simple sample code to reduce amount of ArgumentException answers.
What about InvalidOperationException?
Why not the InvalidEnumArgumentException? It looks like it was designed specifically for this use-case.
Don't throw any specific exception type in the code you're looking at. Call Trace.Assert, or in this case even Trace.Fail to get a similar effect to Debug.Assert, except enabled even in release builds (assuming the settings aren't changed).
If the default trace listener, the one that offers a UI that offers to kill the whole program or launch a debugger, isn't appropriate for your needs, set up a custom trace listener in Trace.Listeners that causes a private exception type to be thrown whenever Trace.Fail is called (including when a Trace.Assert fails).
The exception type should be a private exception type because otherwise, callers may be tempted to try catching whatever exception type you're going to throw. For this particular exception type, you will want to make it as clear as possible that a future version of the method will no longer throw this particular exception. You don't want to be forced to throw a TraceFailedException or whatever you call it from now until eternity to preserve backwards compatibility.
Another answer mentioned Code Contracts already as an alternative. It is, in a similar way: you can call Contract.Assert(false). This takes the same approach of making it customisable what happens if an assertion fails, but in this case, the default behaviour is to throw an exception, again of a type that is not externally accessible. To make the most of Code Contracts, however, you should be using the static rewriter, which has both pros and cons that I will not get into here. If for you the pros outweigh the cons, then by all means use it. If you prefer to avoid the static rewriter though, then I'd recommend avoiding the Contract class entirely, since it is not at all obvious which methods do and don't work.
I think ArgumentOutOfRangeException is valid here and it's what I use. It's the argument to the switch statement that is not handled as it's out of the range of handled values. I tend to code it like this, where the message tells it like it is:
switch (test)
{
case SomeEnum.Woo:
break;
case SomeEnum.Yay:
break;
default:
{
string msg = string.Format("Value '{0}' for enum '{1}' is not handled.",
test, test.GetType().Name);
throw new ArgumentOutOfRangeException(msg);
}
}
Obviously the message is to your own tastes, but the basics are in that one. Adding the value of the enum to the message is useful not only to give detail concerning what known enum member was not handled, but also when there is an invalid enum i.e. the old "(666)SomeEnum" issue.
Value 'OhNoes' for enum 'SomeEnum' is not handled.
vs
Value '666' for enum 'SomeEnum' is not handled.
Here are suggestions that I've been given:
ArgumentException: something is wrong with the value
ArgumentNullException: the argument is null while this is not allowed
ArgumentOutOfRangeException: the argument has a value outside of the valid range
Alternatively, derive your own exception class from ArgumentException.
An input is invalid if it is not valid at any time. While an input is unexpected if it is not valid for the current state of the system (for which InvalidOperationException is a reasonable choice in some situations).
See similar question and answer that I was given.
You should consider using Code Contracts to not only throw exceptions in this case, but document what the failed assumption is, perhaps with a friendly message to the programmer. If you were lucky, the function you called (Whatever) would have a Contract.Ensures which would catch this error before you got your hands on it.
program reaches a logic state that I "know" won't happen, and if it does, something is terribly bad.
In this case, I would throw an ApplicationException, log what you can, and exit the app. If things are that screwed up, you certainly shouldn't try to recover and/or continue.