Which exception to throw when an invalid code path has been taken? - c#

I find myself writing some methods where there is a code path that should never happen. Here is a simplified example:
double Foo(double x) {
int maxInput = 100000;
double castMaxInput = (double)maxInput;
if (x < 0 || x > castMaxInput || double.IsNaN(x)) {
return double.NaN;
}
double r = 0;
for (double boundary = 1; boundary<=castMaxInput; boundary++) {
if (x <= boundary) {
r += boundary * (x + 1 - boundary);
return r;
}
else {
r += boundary;
}
}
// we should never get here.
throw new SomeException();
}
The exception that would make the most sense here is something like
TheAuthorOfThisMethodScrewedUpException()
Because that's what is going on if we reach the end of the for loop. Unfortunately, with the method structured as above, the compiler does not appear to be smart enough to figure out that the code after the for loop should never happen. So you can't just have nothing there, or the compiler will complain that "not all code paths return a value". Yes, I could put in return double.NaN after the loop in addition to before it. But that would disguise the source of the problem.
My question is – is there an exception that would be appropriate?

I use the InvalidOperationException class for that. It means that the application has reached a state it should not be in.
throw new InvalidOperationException("Invalid state.");
You can also Debug.Assert that something is true, or simply Debug.Fail when execution reaches a particular point.
Debug.Fail("This should never happen!");
But debugging asserts/fails don't work in release mode, only when the DEBUG conditional is defined. Depends on your requirements whether that's desirable.
As #AlexD correctly points out, there's also the Trace class with its corresponding Assert and Fail methods, that will work at run-time to help isolate and fix problems without disturbing a running system, when the TRACE conditional is defined (is set by default in the Project Properties Build tab).
By the way, to answer the question in the title: you can create your own exceptions if you want.
[Serializable]
public class TheAuthorOfThisMethodScrewedUpException : InvalidOperationException
{
private const string DefaultMessage = "The author of this method screwed up!";
public TheAuthorOfThisMethodScrewedUpException()
: this(DefaultMessage, null)
{ }
public TheAuthorOfThisMethodScrewedUpException(Exception inner)
: base(DefaultMessage, inner)
{ }
public TheAuthorOfThisMethodScrewedUpException(string message)
: this(message, null)
{ }
public TheAuthorOfThisMethodScrewedUpException(string message, Exception inner)
: base(message, inner)
{ }
protected TheAuthorOfThisMethodScrewedUpException(
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context)
: base(info, context)
{ }
}
And throw it at people.
throw new TheAuthorOfThisMethodScrewedUpException();

As of .NET 7, the UnreachableException should be used.

Don't throw new Exception(), it causes problems for code trying to catch exceptions. The generic, specific exception that you can use is:
throw new InvalidOperationException("Appplication invariants violated");
This assumes you want the error to happen in production, assuming that an error is better than launching missiles and ending the world. Other developers would rather use a method that assumes the invariant can be ignored in production but not at development time and we don't care if we end the world or not.

It looks easy to create a Custom Exception
public class TheAuthorOfThisMethodScrewedUpException: Exception
{
public EmployeeListNotFoundException()
{
}
public EmployeeListNotFoundException(string message)
: base(message)
{
}
public EmployeeListNotFoundException(string message, Exception inner)
: base(message, inner)
{
}
}
then
throw new TheAuthorOfThisMethodScrewedUpException("I am so sorry, this should never happen call me for more info")

Easy! Use the code snippet!
Exception + TAB +TAB
And it will create a new exception for you. This snippet produces this.
[Serializable]
public class MyException : Exception
{
public MyException() { }
public MyException(string message) : base(message) { }
public MyException(string message, Exception inner) : base(message, inner) { }
protected MyException(
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context)
: base(info, context) { }
}
You only need to change the name and.. done! ;)

Related

C# nesting multiple try(s) in multiple if(s) then do the catch(s) After that?

Here What I want to do, but do not know if it will work or if there is a better way:
if (condition1){
try {
Block1;
}
} else if (condition2){
try {
Block2;
}
}
catch(ExceptionType1 ex) { process;}
catch(ExceptionType2 ex) { process;}
catch(Exception) {throw;}
So is that the best way this could be done?
This can do what you want.
try {
if (condition1) {
Block1;
} else if (condition2) {
Block2;
}
}
catch(ExceptionType1 ex) { process;}
catch(ExceptionType2 ex) { process;}
catch(Exception) {throw;}
If not, try to put a clear detailed example.
There is no syntax to support exactly, but you might be able to get a similar effect by defining exception classes, and purposely throwing those exceptions in block1 and block2, either through separate try/catches or if/conditonal statements (checking for null, "", etc.)
Here's an example of an exception class behind defined, taken from here
[Serializable()]
public class InvalidDepartmentException : System.Exception
{
public InvalidDepartmentException() : base() { }
public InvalidDepartmentException(string message) : base(message) { }
public InvalidDepartmentException(string message, System.Exception inner) : base(message, inner) { }
// A constructor is needed for serialization when an
// exception propagates from a remoting server to the client.
protected InvalidDepartmentException(System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
}
In the logic that you want to throw the exceptions in, you just need to define and throw the Exception class you defined. This can be done in a separate catch block, as well
System.ArgumentException argEx = new System.ArgumentException("Index is out of range", "index", ex);
throw argEx;
I'm not sure what you try to achieve with your structure in detail. But I see currently no issue in wrapping the whole statement block into a single try-block #AbdelAzizAbdelLatef mentioned and catch different exception types.
Maybe you can think about, to move your both code blocks (Block1 & Block2) into own functions/methods and perform a specific exception handling there and maybe returning some status code from each new block function. This would be a more clean code approach.

Exception message best practices when aligning messages

We have an exceptions library that is expected to be used over several solutions. We have several custom exception types contained within this library.
The question that has arisen: If we want to align error messages being used in these exceptions, what is the best practise way to accomplish this? For this question, assume that there are 3 or 4 methods across the solutions who want to throw these types of exceptions.
Let's take an example:
public class CustomException : Exception
{
// You can assume that we've covered the other default constructors for exceptions
public CustomException(string message)
: base(message)
{
}
}
The work we want to replace:
public void DoWork()
{
Guid id = Guid.NewGuid();
// ...
throw new CustomException(string.Format("The guid was: {0}.", id));
}
Our current ideas
1/ Define a new constructor that accepts a guid that defines the error message:
const string GuidMessageTemplate = "The guid was: {0}.";
public CustomException(Guid id)
: base(string.format(GuidMessageTemplate, id))
{
}
public void DoWork()
{
Guid id = Guid.NewGuid();
// ...
throw new CustomException(id);
}
2/ Allow each solution to define exception builder classes/methods that instantiate the consistent exceptions
public class ExceptionBuilder()
{
const string GuidMessageTemplate = "The guid was: {0}.";
public CustomException BuildCustomException(Guid id)
{
return new CustomException(string.format(GuidMessageTemplate, id));
}
}
public void DoWork()
{
Guid id = Guid.NewGuid();
// ...
var exception = BuildCustomException(id);
throw exception;
}
3/ Another option?
Use first approach. Your exception should encapsulate building error message. Via constructor exception should recieve only context specific information from outside world.If your exception receive full error message via constructor, then client can create an instance of your exception as follows:
class InvalidEmailException : Exception
{
public InvalidEmailException(string message) : base(message)
{}
}
client code:
void ClientMethod()
{
throw new InvalidEmailException(String.Format("GUID {0} is wrong", Guid.NewGuid()));
}
But wait, I expect Email in this exception!
Approach with exception builder is over engineering, just use first approach :)

Exceptions - Differentiating Exceptions when method raises more than one

I got this class which raises same type of exception, how do i capture this exception and display appropriate error message. Here is what i do now.
public bool ChangePassword(oldPassword,newPassword)
{
if(oldPassword != savedInDatabase)
{
throw new ArgumentException("Your old password is not same as one saved in our database")
}
if(string.IsNullOrEmpty(oldPassword) || string.IsNullOrEmpty(newPassword))
{
throw new ArgumentException("Your old or new password is empty of null");
}
}
and i do the below,
try
{
}
catch(ArgumentException ex)
{
if(ex.Message.contains("Your old or"))
{
messagebox.show("Either your old or new password is empty or null")
}
...
}
Your example does not really justify custom exceptions. I say just display the original message.
However, if you really want to go down the path of custom exceptions, then another option is to create a single custom exception that takes an enum with all the different options, like such:
public class PasswordException : Exception
{
public PasswordException(PasswordResult result) : base() { }
public PasswordException(PasswordResult result, string message) : base(message) { }
public PasswordException(PasswordResult result, string message, Exception innerException) : base(message, innerException) { }
}
public enum PasswordResult
{
Success = 0,
PasswordMismatch,
PasswordEmpty,
// and so forth
}
You might consider throwing different exception types. If you wished to stick with the library exception types an ArgumentNullException would be appropriate if the old or new password is null or empty. Alternatively you may consider defining your own exception types with a more specific error (perhaps similar to FaultExceptions in WCF), or including a resource identifier in your custom exception (to ensure I18N compatible):
public class ResourceableException : Exception
{
public string ResourceKey { get;set; }
}
Then used like so:
try { ... }
catch (ResourceableException e)
{
messagebox.Show(ResourceManager.GetResource(e.ResourceKey));
}
You can create custom exceptions like this:
public class PasswordEmptyOrNullException : Exception
{
public PasswordEmptyOrNullException(string message)
: base(message)
{
}
}
public class OldPasswordNotFoundException : Exception
{
public OldPasswordNotFoundException(string message)
: base(message)
{
}
}
They can then be used like this:
throw new PasswordEmptyOrNullException("A message");
Then you can handle them in a try catch statement like this:
try
{
}
catch (PasswordEmptyOrNullException ex)
{
// Do stuff
}
catch (OldPasswordNotFoundException ex)
{
// Do stuff
}
So you can handle different types of exceptions in different ways. Hope that's what you were looking for.

C# re-throwing exception outside of scope

I am fully aware that what I am about to ask is not good practice... but:
Let's say I have a class containing a function that I want to always return a value, but store any exceptions that might occur for later processing. Something Like:
public Exception _error { get; set; }
public bool IsValid()
{
try
{
//do something here to cause exception
return true;
}
catch (Exception ex)
{
_error = ex;
return false;
}
}
Now that I have stored the exception, is it at all possible to throw the exception from an outside method while maintaining both the original stack trace and exception type?
throw _error; //lose stack trace
throw new Exception("", _error) //lose type
Thanks for looking or answering.
EDIT:
Thanks to some additional points, I realize that the below idea only takes away information and doesn't really add or simplify the situation. Thanks again to everyone.
After pondering Pieter's answer and comments, I'm now wondering if making a wrapper Exception class like the below could be a partial solution. This overrides as much of the exception as possible to make the New exception look like its innerexception, including the stacktrace.. dirty I know, but interesting:
public class ExceptionWrapper : Exception
{
private Exception _innerException;
public ExceptionWrapper(Exception ex) : base("", ex)
{
_innerException = ex;
this.Source = ex.Source;
this.HelpLink = ex.HelpLink;
}
public override string StackTrace
{
get
{
return _innerException.StackTrace;
}
}
public override System.Collections.IDictionary Data
{
get
{
return _innerException.Data;
}
}
public override string Message
{
get
{
return _innerException.Message;
}
}
public new Exception InnerException
{
get
{
return _innerException.InnerException;
}
}
}
No, this is not possible.
However, you normally solve this is by wrapping the exception in a new exception:
throw new MyException("Wrapper", _error);
This does maintain the stack trace of _error, but you do get a new exception. Your solution in your second example is the correct way of handling these cases.
Consider using reflection to create a wrapper exception of the correct type (Activator.CreateInstance) and calling the constructor that will accept the inner exception you have stored.
For example:
[Test]
public void test()
{
Exception ex = new ArgumentNullException();
Exception wrapped = (Exception)Activator.
CreateInstance(ex.GetType(), "wrapped", ex);
Type expectedType = typeof(ArgumentNullException);
Assert.IsInstanceOf(expectedType, wrapped, "Is ArgumentNullException.");
Assert.AreEqual(ex, wrapped.InnerException, "Exception is wrapped.");
}
Update
In order to mitigate the constructor issue, you could consider using the default constructor (should be there for an exception that follows design guidelines, but not mandatory) and then patching up the new instance by setting its fields via reflection.
I agree the approach is highly "meh" it's more an exploration of an idea. I wouldn't recommend it.
The exception design guidelines require a default constructor, so this sort of behaviour may go on in the framework somewhere anyway. Perhaps for some sort of icky serialization\deserialization of exceptions across some sort of communications boundary?
It seems that .net-4.5 added a new API for capturing stack/info about exceptions and rethrowing them in different contexts. This is called ExceptionDispatchInfo. It is useful if you find yourself needing more control over running tasks indirectly, like if you do manual thread management for jobs or Task does not exactly fit your needs. In your example, it should look like this:
public ExceptionDispatchInfo _error { get; private set; }
public bool IsValid()
{
try
{
//do something here to cause exception
return true;
}
catch (Exception ex)
{
_error = ExceptionDispatchInfo.Capture(ex);
return false;
}
}
/// <summary>Throw underlying exception if invalid.</summary>
public void AssertWasValid() => _error?.Throw();
Now, it doesn’t preserve the original caller. The displayed stack trace shows the calls from the original try block into the code in there, a statement breaking the original and new parts of the stack, and then the calls into ExceptionDispatchInfo.Throw() itself as the new part of the shown stack. This seems similar to how traces with async code look. If you care about the original caller, seems this won’t work. But if you care about getting the line/method that threw the exception, this should be sufficient.

C#: Exception to throw when a certain type was expected

I know this sort of code is not best practice, but nevertheless in certain situations I find it is a simpler solution:
if (obj.Foo is Xxxx)
{
// Do something
}
else if (obj.Foo is Yyyy)
{
// Do something
}
else
{
throw new Exception("Type " + obj.Foo.GetType() + " is not handled.");
}
Anyone know if there is a built-in exception I can throw in this case?
If obj is an argument to the method, you should throw an ArgumentException:
throw new ArgumentException("Type " + obj.Foo.GetType() + " is not handled.", "obj");
Otherwise, you should probably either throw an InvalidOperationException or create your own exception, like this:
///<summary>The exception thrown because of ...</summary>
[Serializable]
public class MyException : Exception {
///<summary>Creates a MyException with the default message.</summary>
public MyException () : this("An error occurred") { }
///<summary>Creates a MyException with the given message.</summary>
public MyException (string message) : base(message) { }
///<summary>Creates a MyException with the given message and inner exception.</summary>
public MyException (string message, Exception inner) : base(message, inner) { }
///<summary>Deserializes a MyException .</summary>
protected MyException (SerializationInfo info, StreamingContext context) : base(info, context) { }
}
You could use System.NotSupportedException or just make your own exception based on Exception.
Take a look here for a comprehensive list of exceptions. Unfortunately, I don't think any of them fits your problem. It's better to create your own.
perhaps System.InvalidOperationException (whatever operation your method is meant to do cannot be done on this data type) ? Or make your own as the others are suggesting
If obj is a parameter to your method, I'd throw an ArgumentException. Otherwise, in this case, I'd probably roll my own.
See this Q/A for a rundown on exception guidelines. Basically, there's some built in exceptions that are considered off limits to throw outside the framework. ArgumentException is one of them that is OK.
Coincidentially, today i found a very nice class from Jared Pars's Weblog, here where he explains a SwitchType class for dealing with this kind of situations.
Usage:
TypeSwitch.Do(
sender,
TypeSwitch.Case<Button>(() => textBox1.Text = "Hit a Button"),
TypeSwitch.Case<CheckBox>(x => textBox1.Text = "Checkbox is " + x.Checked),
TypeSwitch.Default(() => textBox1.Text = "Not sure what is hovered over"));

Categories

Resources