How to throw meaningful exceptions in F# and catch them in C#?
With the following code:
F# Library:
module Test
exception TestExc of string
let throwit message : unit=
raise (TestExc("custom exception with message: " + message))
C# Client:
namespace TestExc
{
class Program
{
static void Main(string[] args)
{
try
{
Test.throwit("Hi there");
}
catch (Test.TestExc te)
{
Console.WriteLine("Caught exception with message: " + te.Message);
}
}
}
}
I get the following message:
Caught exception with message: Exception of type 'Test+TestExc' was thrown.
But I want to see Hi there as the caught exception message.
What is the F# equivalent of the following?
class CSTestExc:System.Exception
{
public CSTestExc(String message) : base(message) { }
}
Rather than creating exception using exception TestExc of string create exception as :
type MyExp (msg:string) =
inherit Exception(msg)
Related
I am currently practicing creating my Exception class. The idea of this code is for the user to enter a password. In case its code is less than 5 characters, the program will throw an exception. I want that my program throw one exception with text("Password is too small") and the object of my Exception class use ToString method(where will write " Password Length Exception").What confuses me is why I get the message Unhandled exception.Password Length exception. Cannot print exception string because Exception.ToString () failed. You can see this in the photo
Here is my code.
public class My_Exception : Exception
{
public My_Exception(string message) : base(message)
{
Console.WriteLine(message);
}
public override string ToString()
{
throw new My_Exception(" Password Length exception ");
}
}
class Program
{
static void Main(string[] args)
{
try
{
Console.WriteLine("Enter your password");
string Password = Console.ReadLine();
if (Password.Length < 5)
{
throw new My_Exception(" Password is too small ");
}
}
catch(My_Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
Remove the override .ToString().
public class My_Exception : Exception
{
public My_Exception(string message) : base(message)
{
Console.WriteLine(message);
}
}
The message will be shown by the base Exception.ToString(). You shouldn't thow an exception from another exception.
And in truth, you shouldn't Console.WriteLine() from inside the constructor of an Exception. It is the try/catch block that should print in any way it wants the exception.
public class My_Exception : Exception
{
public My_Exception(string message) : base(message)
{
}
}
See running example at https://ideone.com/FchSGc
Don't throw an exception in the .ToString method. Return a string with information about what happened.
public override string ToString()
{
return " Password Length exception ";
}
Or simply create a proper exception
public class PasswordToSmallException : Exception
{
public PasswordToSmallException()
: base("Password should be at least 5 characters")
{}
}
And then you just
catch(Exception ex)
{
Console.WriteLine(ex);
}
Problem : cannot print exception string because exception.tostring() failed
Solution : I think it is a problem with the computer. I had this message also. I just restart the computer and it work.
We have a very large complicated application that has a ThreadException handler intialized at startup, and any exceptions thrown by the application that are not handled immediately are handled by this ThreadException handler in a unified way.
This mostly works...but we have a couple custom exception types that we want to handle with this exception handler, and for some reason these exception types always show up in the ThreadException handler as just System.ComponentModel.Win32Exception types, instead of our custom types.
I've tried anything I can think of to troubleshoot, including making sure our custom exception classes implement all recommended constructors, including a serialiation constructor.
Additional info...when I create a new exception with just the message from the existing exception, this comes through as a System.Exception. For example:
MSCSqlException msx = new MSCSqlException(sqlQuery, sqlParams, sqlException);
throw new Exception(ex.Message);
works fine and is caught in the exception handler as a System.Exception.
However, if I try something like:
MSCSqlException msx = new MSCSqlException(sqlQuery, sqlParams, sqlException);
throw new Exception(ex.Message, ex);
Then the exception manager catches the above System.ComponentModel.Win32Exception instead of just a System.Exception.
Just for completeness, what I WANT to do is something like:
throw new MSCSqlException(sqlQuery, sqlParams, sqlException);
and have the Application.ThreadException handler receive a properly typed MSCSqlException.
Any ideas how to get around this? Is there some quirk of Application.ThreadException that I'm missing related to custom error types?
Our custom exception class:
[Serializable]
public class MSCSqlException : Exception
{
public string SqlCommand { get; private set; }
public object[] SqlParameters { get; private set; }
public MSCSqlException()
{
}
public MSCSqlException(string message)
: base(message)
{
}
public MSCSqlException(string message, Exception inner) : base(message, inner)
{
}
public MSCSqlException(string command, object[] parameters, SqlException sx) : base(CreateUsefulMessage(sx, command, parameters), sx)
{
SqlCommand = command;
SqlParameters = parameters;
}
protected MSCSqlException(SerializationInfo info, StreamingContext context) : base(info, context)
{
SqlCommand = info.GetString("SqlCommand");
}
[SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
if (info == null)
{
throw new ArgumentNullException("info");
}
info.AddValue("SqlCommand", SqlCommand);
base.GetObjectData(info, context);
}
public static string CreateUsefulMessage(SqlException sx, string sqlCommand, object[] sqlParameters)
{
string message = sx.Message + Environment.NewLine;
if(sqlParameters != null && sqlParameters.Count() > 0)
{
message = message + "Parameters:" + Environment.NewLine;
foreach(object sp in sqlParameters)
{
message = message + "\t" + sp.ToString() + Environment.NewLine;
}
}
message = message + "SQL Statement:" + Environment.NewLine;
message = message + sqlCommand;
return message;
}
}
We finally figured this out...the issue is a bug or feature in how .Net handles exceptions thrown in a background worker Completed event. For whatever reason, it appears that in this case, the .Net run time is passing the innermost exception from the stack trace to the ThreadException handler instead of the expected outermost exception. This innermost exception when a SQLException is thrown is a Win32Exception.
More info on this here:
Application.ThreadException is getting incorrect Win32Exception type
try
{
}
catch (Exception objEx)
{
clsLog.blnLogError(this.GetType().Name, MethodBase.GetCurrentMethod().Name, String.Format("Error In {0}...", MethodBase.GetCurrentMethod().Name), objEx.Message);
}
This is my Code and I need something like.
catch (MyException objEx)
{
}
class MyException
{
method()
{
//method overload with necessary parameters.
clsLog.blnLogError(this.GetType().Name, MethodBase.GetCurrentMethod().Name, String.Format("Error In {0}...", MethodBase.GetCurrentMethod().Name), objEx.Message);
}
}
In that exception class I need to get the curent class name and method name instead of writing every time.
How to achieve this?
UPDATE
[Serializable]
public class MyException : Exception
{
public MyException(string message, Exception innerException, object obj)
: base(message, innerException)
{
}
}
try
{
int f = int.Parse("d");
}
catch (MyException objEx)
{
}
It is not catching the exception and I need the method name, class name of the one where it throws error.
This cannot be done by inheriting, you will need to write an extension method so that you can call your logging method on all exception types, no matter whether they were declared by yourself or not.
To create an extension method create a static class containing a static method doing your work. Prepend the first argument of the method with the keyword this, indicating to the compiler that this method can be invoked like a member method on objects of the type of the first parameter (in your case Exception):
public static class ExceptionExtensions
{
public static void Log(this Exception ex)
{
var stackTrace = new StackTrace();
var callingMethod = stackTrace.GetFrame(1).GetMethod();
var methodName = callingMethod.Name;
var className = callingMethod.DeclaringType.Name;
clsLog.blnLogError(className, methodName, string.Format("Error In {0}...", methodName), ex.Message);
}
}
then you can call that method on every exception:
try
{
int f = int.Parse("d");
}
catch(Exception ex)
{
ex.Log();
}
For more information on extension methods see the C# Programming Guide.
I've written a custom exception AbortTestException, which is pretty simple:
class AbortTestException : Exception
{
public AbortTestException(string message)
: base(message) { }
}
Then I have a function that will throw it:
class Foo
{
public void Throws()
{
throw new AbortTestException("hi");
}
}
And Throws() gets called via method reference:
class Program
{
static void Main(string[] args)
{
Type myType = (typeof(Foo));
var method = myType.GetMethod("Throws");
try
{
method.Invoke(new Foo(), null);
}
catch (AbortTestException ex)
{
Console.WriteLine("AbortTestException");
}
catch (Exception ex)
{
Console.WriteLine("Exception");
}
}
}
However, something weird happens. Even though Throws rises an AbortTestException, the catch(Exception) block gets used (instead of the catch(AbortTestException) block). I tried putting the "throw new AbortTestException("hi")" portion in the try block itself, and verified that the correct catch block is used.
Is there some reason an exception would be re-cast when emitted via MethodInfo.invoke()?
http://msdn.microsoft.com/en-us/library/4k9x6bc0.aspx
Per the MSDN a TargetInvocationException is thrown if the invoked method or constructor throws an exception.
Did you check the nested Exception? My guess the original exception (AbortTest...) is wrapped in a nested one. The nested Exception will be in the InnerException property of the one which is caught by your code
Remember that catching Exception will match any exception that isn't caught by a more specific catch block before it:
Type myType = (typeof(Foo));
var method = myType.GetMethod("Throws");
try
{
try
{
method.Invoke(new Foo(), null);
}
catch (AbortTestException ex)
{
Console.WriteLine("AbortTestException");
}
catch(TargetInvocationException tie)
{
throw tie.InnerException;
}
catch (Exception ex)
{
Console.WriteLine("Exception");
}
}
catch(AbortTestException ate)
{
Console.WriteLine("AbortTestException after re-throw from TargetInvocationException");
}
I am using the following system.exception derived exception in the following manner and would expect the exception thrown in SomeFunction to be caught in the catch block in SomeOtherFunction but instead I receive an unhandled exception error when the code attempts to throw the exception, any insight would be appreciated.
void SomeFunction()
{
if (someValue == false)
{
throw(new MyException("some error, falseValue,null);
}
}
void SomeOtherFunction()
{
try
{
SomeFunction();
}
catch(MyException ex)
{
}
}
public class MyException : Exception
{
public MyException (string message, Reason reason, Exception innerException)
: base(message, innerException)
{
Reason = reason;
}
public Reason Reason { get; private set; }
}
There must be other code that is contributing to this issue - here is a complete example that works:
using System;
class Example
{
static void Main()
{
SomeOtherFunction();
}
static void SomeFunction()
{
throw new MyException("some error");
}
static void SomeOtherFunction()
{
try
{
SomeFunction();
}
catch (MyException)
{
Console.WriteLine("caught the exception");
}
}
}
class MyException : Exception
{
public MyException(string message)
: base(message) { }
}
Perhaps you can use this example and work backwards to see if there is something missing from your real code? Since there were compilation issues with your examples I am assuming that you have sanitized some production code.
I see some minor syntax errors. But I think your unhandled exception error might be coming from the constructor of MyException or the way you're handling Reason in your constructor/get,set methods. It seems like you're trying to set a value to a class, but I'm still trying to migrate from c++..so idrk what im talking about.
Try fixing syntax and working with your "Reason"