throw new CustomException vs. Marshal.ThrowExceptionForHR - c#

I have a question regarding Exceptions and returning control to a COM caller. Below is a test question with a custom exception class. What is the difference between
Marshal.ThrowExceptionForHR(CustomException.COR_E_ARGUMENT);
and
throw new CustomException("Argument is out of bounds");
I kind of get why 1) and 2 doesn't work as they return an int and an Exception-object. But what's the difference between 3 and 4?
public class CustomException : ApplicationException
{
public static int COR_E_ARGUMENT = unchecked((int)0x80070057);
public CustomException(string msg)
: base(msg)
{
HResult = COR_E_ARGUMENT;
}
}
You need to write a code segment that will use the CustomException class
to immediately return control to the COM caller. You also need to ensure
that the caller has access to the error code. Which code segment should
you use?
return Marshal.GetExceptionForHR(CustomException.COR_E_ARGUMENT);
return CustomException.COR_E_ARGUMENT;
Marshal.ThrowExceptionForHR(CustomException.COR_E_ARGUMENT);
throw new CustomException("Argument is out of bounds"); // correct answer

The COM client code is of course completely agnostic of the .NET Exception type, it only sees the HRESULT error code. So there is no value-add from adding your own exception types.
All standard .NET Exception derived classes already have a precooked HRESULT value baked-in. They assign the Exception.HResult property in their constructor. If you want to generate E_INVALIDARG (0x80070057) then use the standard .NET exception class that already uses that error code. System.ArgumentException.

Related

Custom Exception Handler C#

I have Made custom Exception Handler in C# I want to show a readable message for the user if any Exception occurred.
I have tried to specify the Exception pending on it's Hresult Value but I have a problem that I haven't seen, which is showing Hresult value and the specified exception
class UiException : Exception
{
public string Errormessage { get; set; }
public UiException(Exception e)
: base()
{
string exName = e.Source;
int errorNumber = e.HResult;
if (e.HResult == -2146233080)
Errormessage = "Index was outside the bounds of the array.";
}
}
You do not want to use HRESULT for exception identification. HRESULT is mainly there for COM interop and is of little use in .NET. I would recommend the following:
Use the type of the base exception to figure out your custom error message. You stay in .NET and it is more flexible. The main advantage in terms of flexibility is that you can easily cover exceptions derived from other exceptions without having to define a fallback. Also, with an ascast you can easily extract further information from the exception (such as the ParameterName of an ArgumentException).
Make your base exception an inner exception. Inner exceptions are there since the dawn of time .NET and therefore are widely supported, e.g. for logging or debugging. Keeping the source of the error is also good for error analysis and general best practice.
There is absolutely no need for your Errormessage property. There is a Message property, which suits your purpose and (like the inner exception) is widely supported.
So your custom exception should look more like this:
class UIException : Exception
{
public UIException(Exception baseException) :
base(GetErrorMessage(baseException), baseException)
{
}
private static GetErrorMessage(Exception baseException)
{
if (baseException is IndexOutOfRangeException)
{
return "Index was outside the bounds of the array.";
}
else if (exception is InvalidOperationException)
{
//Return exception message
}
//... more else if in the chain
else
{
return baseException.Message;
}
}
}

C# instantiate generic type from method signature

I've been fooling around with generic methods lately and came across methods that look like this:
public static void Requires<TException>(bool condition, string message) where TException : Exception
To my understanding, when using the above method you provide a Type that inherits from Exception and if the condition is false the provided Exception type is thrown.
How does this work under the hood?
Is the TException instantiated like so throw new TException();?
And how can you pass in the message parameter if the Type is unknown to the method (all it knows is that it inherits type Exception)?
According to MSDN : System.Exception does have constructor that takes a string as argument. This string represents the message.
With the help of the Activator-Class you can do the following pretty simple:
using System;
public class Test
{
public static void Requires<TException>(bool condition, string message)
where TException : Exception
{
Exception exception = (Exception)Activator.CreateInstance(typeof(TException),message);
throw exception;
}
public static void Main()
{
try
{
Requires<ArgumentNullException>(true,"Test");
}
catch(Exception e)
{
Console.WriteLine(e);
}
}
}
Working example:
http://ideone.com/BeHYUO
To my understanding, when using the above method you provide a Type that inherits from Exception and if the condition is false the provided Exception type is thrown.
That depends on the implementation of the method, all it is saying is that the type parameter of the Requires method must have a base type of Exception. But it is highly likely that it creates an exception of that type if the condition is false. One way to do that is with Activator.CreateInstance method.
And how can you pass in the message parameter if the Type is unknown
to the method
Similarly to Ned Stoyanov's answer, it's up to the person implementing the method to decide how this parameter will be used. It can be used as a message imbedded in the exception, it can be used somewhere else or it can be not used at all. The parameter name only suggests what it will be used for, but the caller has no guarantee that it will be used as he expects. It could be called djfhsfjfh as well .

Catching base but not sub exceptions

I am writing a HttpHandler and as part of my internal design, I throw different exceptions and catch them at the top level in order to determine what status code to set the request to.
I.e.
ArgumentException triggers Bad Request
AuthenticationException triggers Unauthorised
OracleException triggers InternalServerError
etc
The problem I've found is that I was using InvalidOperationException to trigger NotFound, but a bug in my code caused me to realise that, of course, some system exceptions inherit from these base system exceptions, which causes unexpected responses.
I.e. I found that ObjectDisposedException inherits from InvalidOperationException, which means that the response returns a 404 instead of 500.
Is there a way to catch just the base exception?
I found this thread which suggests I could do a filter and rethrow, but that seems hacky.
Would I be better off just creating my own exception types to save all this hassle?
If you only want to pass the HTTP result code (and maybe error message line) to the client, then I recommend you create a single custom exception:
public class MyCustomException : Exception { // Or maybe InvalidOperationException
public int StatusCode {get;set;}
public string Status {get;set;}
}
etc.
As far as I am aware there's no way to catch an exception but not catch inherited exceptions. The problem is that you're considering the base exception to be more specific than the inherited exception, which is the opposite of how they're intended to work (Inherited exceptions should be more specific subsets of their parent, so conceptually if you can handle the parent you should be able to handle the inherited exception).
Your options basically are:
Create your own exception type & only catch this. If your exception falls under the definition of an InvalidOperationException then you can inherit from this. Then you can catch yours specifically.
Catch, inspect, and re-throw if it's not what you're after. This technique I typically try to avoid but is sometimes required if exception types are too generic. e.g.
catch (InvalidOperationException ex) {
if (ex.GetType() != typeof(InvalidOperationException)) throw;
/* Do stuff */
}
It is not possible to only catch base exceptions.
In this case it is best to create a custom exception, rather than use the system's exception types.
public class HttpErrorException : Exception
{
public HttpStatusCode StatusCode { get; private set; }
public HttpErrorException(HttpStatusCode code, string message)
: base(message)
{
this.StatusCode = code;
}
}
throw new HttpErrorException(400, "You sent a bad request!");
If the original intention was to obfuscate the HTTP status codes, and instead use their text names, factory methods can be created.
public class HttpErrorException : Exception
{
public HttpStatusCode StatusCode { get; private set; }
private HttpErrorException(HttpStatusCode code, string message)
: base(message)
{
this.StatusCode = code;
}
public static HttpErrorException BadRequest(string message)
{
return new HttpErrorException(400, message);
}
public static HttpErrorException InternalServerError(string message)
{
return new HttpErrorException(500, message);
}
// etc
}
throw HttpErrorException.BadRequest("You made a bad request!");

Try-Catch exception handling in constructor method

I have a seperate class file which contains a constructor method among other methods and I create an instance of this class within a Windows form. I need to do some exception handling within the constructor method, if the required file doesn't exist then catch it with a FileNotFoundException. My only issue is I have no idea how to pass the results of the exception to the Windows form since I can't pass arguments or return any data from the constructor class.
You're making a conceptual mistake. A constructor has a single purpose in life: to prepare a class instance for its busy lifetime. It can therefore have only 2 possible outcomes:
Construction succeeds. The object is usable.
Construction fails because construction was aborted by an exception.
If the file you mention is vital for the object to function, you shouldn't catch the exception and just let it slip outside to the instantiator. It wouldn't make sense in that case to 'return some error' and leave the object half-usable. The event handler in your form should catch the exception and communicate it to the user.
If there is a use case in which a usable object may still be returned, you should implement a static method, something like public static MyClass instantiateConditionally(string filename, out bool somethingHappenedAlongTheWay). This would allow you to return an instance still, and return that something went wrong.
Do you need the object to be successfully constructed even if the exception is thrown?
If you don't then don't handle the exception in the constructor; handle it in the windows form method where you are creating the object.
If you do, then I'd suggest implementing in your object a Boolean property HasErrors that returns true if exception(s) were handled in the constructor. Also implement a method GetErrors() which returns any handled exceptions (conveniently stored in an instance field) or null. This way you can always check in your windows form method if any exception was thrown during the creation of the object and act accordingly.
Do you mean something like this?
public class Form1 : Form
{
...
public void button_Click(...)
{
try
{
var myclass = new MyClass(#"C:\...some file");
...
}
catch (FileNotFoundException)
{
MessageBox.Show("Can't find the file required");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
public class MyClass
{
public MyClass(string path)
{
if(string.IsNullOrEmpty(path))
throw new ArgumentNullException();
if(!File.Exists(path))
throw new FileNotFoundException();
...
}
}
Here i create an instance of MyClass when the user clicks on some button.
The class contructor of MyClass throws an exception if no path is given or if the file is not found at the specified path.
I use a try catch to catch any exception thrown and display a messagebox to the user.

How to throw custom exception when exception type was passed by constructor

I've created class that takes Exception type in constructor
private readonly Exception _exception;
public StringToObject(Exception exception)
{
_exception = exception;
}
i wanted to throw exception
throw new _exception("");
but i got error:
'._exception' is a 'field' but is used like a 'type'
is any possible ways to throw it?
This is not a good practice at all. Doing so will cause you to lose your stack trace related information. Please consider reading this section of Eric Lippert's blog:
Too Much Reuse
When you write
throw new Exception();
you instantiate this new exception. But then, since your private member _exception is already instantiated, you don't need to re-instantiate it, that is instantiating an instance, which doesn't make sense. Instead, use the following:
throw _exception;
This will do it.
To rethrow an existing exception like that use
throw _exception;
However, that will modify the call stack in the exception instance, so you will lose the original source of the exception. If you want to avoid that, you can throw a new exception with the instance as an inner exception.
I'm actually very confused about why you want to do this? Are you trying to create a custom exception to provide more information? If so, then you want to use this pattern.
First define a custom exception class that derives from Exception:
public class MyCustomException : Exception // Or you could derive from ApplicationException
{
public MyCustomException(string msg, Exception innerException)
: base(msg, innerException)
{
}
}
You could also define additional parameters in your custom exception constructor to contain even more information if you wish. Then, in your application code...
public void SomeMethod()
{
try
{
// Some code that might throw an exception
}
catch (Exception ex)
{
throw new MyCustomException("Additional error information", ex);
}
}
You'll want to be sure to keep track of the inner exception, because that will have the most useful call stack information about what caused the exception in the first place.
throw _exception;
This example should work. I´ve included all the classes involved in the example.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
public class MyException : Exception
{
public MyException(string message) : base(message)
{}
//...
}
public class MyClass
{
private Exception exception;
public MyClass(Exception e)
{
this.exception = e;
}
public void ThrowMyException()
{
throw exception;
}
}
class Program
{
static void Main(string[] args)
{
MyException myExceptionInstance = new MyException("A custom message");
MyClass myClassInstance = new MyClass(myExceptionInstance);
myClassInstance.ThrowMyException();
}
}
}
I suspect that what you're really looking for is to throw a new exception of your suggested type, in which case passing in a "Type" parameter (or even using a generic) would be the way forward.
However, I can't imagine a situation where this is a sensible design choice, so I'd have to urge you to reconsider (and perhaps post more of your requirements so that someone can suggest a better alternative!).

Categories

Resources