Is there a way to detect the exception in dispose? - c#

I have the following scenario:
class Program
{
static void Main(string[] args)
{
try
{
using (new Foo())
{
throw new Exception("Inside using block");
}
}
catch (Exception e)
{
}
}
}
public class Foo : IDisposable
{
public void Dispose()
{
throw new Exception("Inside dispose");
}
}
Is it somehow possible, to get the thrown exception - "Inside using block" - in the Dispose method of Foo and make it an InnerException of the Exception Inside dispose?
Edit:
For example:
class Program
{
static void Main(string[] args)
{
try
{
using (var fi = new FileHandler())
{
//open the file
fi.Open();
//write to the file
fi.Write();
//excption occurs
throw new Exception("Inside using block");
fi.Close();
}
}
catch (Exception e)
{
//now I only have the exception from the dispose but not the exception that occured in the using block itself
//I know I could wrap the code inside the using in a try/catch itself, just asking if it is possible without 2 try/catches
}
}
}
public class FileHandler : IDisposable
{
public void Dispose()
{
//Close the file
//for some reason it fails with an exception
throw new Exception("Inside dispose");
}
}

Per the Framework Design Guidelines (Cwalina, Abrams), section 9.3:
AVOID throwing an exception from within Dispose(bool) except under critical situations where the containing process has been corrupted.
If Dispose could raise an exception, further finally block cleanup logic will not execute. To work around this, the user would need to wrap every call to Dispose (within their finally block!) in a try block, which leads to very complex cleanup handlers. If executing a Dispose(bool) method, never throw an exception if disposing is false.
Also from section 9.3:
AVOID making types finalizable. Carefully consider any case in which you think a finalizer is needed. There is a real cost associated with instances with finalizers, from both a performance and code complexity standpoint."

Related

using statement with fluent api will not call dispose if throw occurs in fluent method chain

When combining a using statement with a fluent api that can potentially throw, the lowered code will never call dispose correctly.
If I have the following class that exposes a fluent interface:
public class Wrapper : IDisposable
{
private bool _isAdded;
public Wrapper Add()
{
_isAdded = true;
return this;
}
public void Dispose() => Console.WriteLine("dispose called");
public Wrapper ThrowIfAdded() => _isAdded ? throw new Exception() : this;
}
and I call it with the following:
using var willNotDispose = new Wrapper().Add().ThrowIfAdded();
the lowered code will result in the Dispose call occurring after the fluent method chain is completed.
Wrapper willNotDispose = new Wrapper().Add().ThrowIfAdded();
try
{
}
finally
{
if (willNotDispose != null)
{
((IDisposable)willNotDispose).Dispose();
}
}
Alternatively, if the call to .ThrowIfAdded() is done outside of the initial using declaration,
using var willDispose = new Wrapper().Add();
willDispose.ThrowIfAdded();
the lowered code is generated as expected.
Wrapper willDispose = new Wrapper().Add();
try
{
willDispose.ThrowIfAdded();
}
finally
{
if (willDispose != null)
{
((IDisposable)willDispose).Dispose();
}
}
While I understand why this is occurring, it isn't desirable. Is there any way to coerce the former initialization to compile to the latter? Ideally, it would be an attribute or form of compiler hint that would result in:
Wrapper willDispose = default;
try
{
willDispose = new Wrapper().Add().ThrowIfAdded();
}
finally
{
if (willDispose != null)
{
((IDisposable)willDispose).Dispose();
}
}
which I would have expected the original example to compile to in the first place.
As pointed out in the comments, there is pre-existing guidance that when an exception is thrown in a constructor, it should be explicitly handled and the resources cleaned up.
This extends to CA2000 analysis that states:
When constructors that are protected by only one exception handler are
nested in the acquisition part of a using statement, a failure in the
outer constructor can result in the object created by the nested
constructor never being closed. In the following example, a failure in
the StreamReader constructor can result in the FileStream object never
being closed. CA2000 flags a violation of the rule in this case.
using (StreamReader sr = new StreamReader(new FileStream("C:/myfile.txt", FileMode.Create)))
{ ... }
While a Fluent API throwing an exception is not explicitly either a constructor or nested constructor throwing an exception, it should be treated the same since the object will be created and mutated outside of the try/finally block.
As a result, any method that can throw must first call dispose before allowing the exception to propagate.
public class Wrapper : IDisposable
{
private bool _isDisposed;
private bool _isAdded;
public Wrapper Add()
{
_isAdded = true;
return this;
}
public void Dispose()
{
if (_isDisposed)
{
return;
}
_isDisposed = true;
Console.WriteLine("dispose called");
}
public Wrapper ThrowIfAdded()
{
if (_isAdded)
{
Dispose();
throw new Exception();
}
return this;
}
}
This correctly assures that in cases where .Added() is called, .ThrowIfAdded() will dispose prior to throwing.
If .Added() is not called, the instance will be disposed at the end of the block as expected.

Can I overload the throw keyword?

I want to overload the throw keyword to catch a class which inherits from Exception and to have it do some logging and other stuff before the actual throw. Is this possible? Or do I have to use a regular function?
I've tried:
public class cSilException : Exception
{
private string m_strMsg;
public override void throw(cSilException ex)
{
}
...
...
}
Register the event AppDomain.FirstChanceException. There you get all exceptions before the are actually thrown. In the event handler you can check for your exception and do the required logging.
No magic and no bad design.
class Program
{
static void Main(string[] args)
{
AppDomain.CurrentDomain.FirstChanceException += CurrentDomain_FirstChanceException;
DoBadThings();
}
private static void DoBadThings()
{
DoOneLevelBelow();
}
private static void DoOneLevelBelow()
{
for(int i=0;i<10;i++)
{
try
{
if (i == 5)
{
var invalidCast = (string)((object)i);
}
else
{
throw new InvalidTimeZoneException();
}
}
catch
{
}
}
}
static void CurrentDomain_FirstChanceException(object sender, System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs e)
{
if( e.Exception is InvalidCastException)
{
LogInvalidCast((InvalidCastException)e.Exception);
}
}
private static void LogInvalidCast(InvalidCastException invalidCastException)
{
Console.WriteLine("Got Invalid cast: {0}", invalidCastException);
}
This will lead to:
Got invalid cast: System.InvalidCastException: The object of the type
"System.Int32" cannot be converted to "System.String". at
ThrowTest.Program.DoOneLevelBelow() in
d:\Media\Blog\ThrowTest\Program.cs:line 31.
Please note since you are getting the exception before the stack is unwound you will see only the method where it did happen but not the calling methods since the stack was not unwound yet.
If you want the complete call stack you can use Environment.StackTrace to get all stack frames.
What you want to do is add a constructor to your exception and do whatever you need to do within that constructor.
public class cSilException : Exception
{
//constructor
public cSilException()
{
// do stuff here
}
}
Your notion of "overloading the throw keyword" was quite, er, how to put it, psychedelic.
Of course, as many have pointed out, it is best to avoid doing this if your intention is to do things such as logging. Alois Kraus has posted another answer with a very good suggestion.
I wouldn't recommend logging anything inside the exception's constructor since it violates the single responsibility principle and is considered a bad design. Also, the fact that an exception was created doesn't necessarily mean it has been thrown, and besides, exceptions can be caught and rethrown - these things may lead to incorrect logging messages.
Instead, you can use an application-wide exception handler which will handle exceptions according to your predefined policy. For example, you can have a look at the Enterprise Library Exception Handling Block and specifically this section.
You can't overload throw it is an integral part of the language (not a member of a class)
If you want to handle a specific Exception you should catch that exception:
try
{
// your code, which throws some exceptions
}
catch(cSilException csEx)
{
// handle csEx
throw; // rethrow this exception
}
catch(Exception ex)
{
// handle all other exceptions
}
This code catches the special exception cSilExceptionin a different code block than all other exceptions.
Look for methods and members of Exception class. You can define constructor for cSilException like this
public cSilException(string message)
{
Message = message;
}
and than in catch (cSilException ex) do Console.WriteLine(ex.Message);

How constructor calling occurs in case of c# custom exception handling?

Here's is my program
class Program
{
static void Main(string[] args)
{
throw new UserAlreadyLoggedInException("Hello");
}
}
public class UserAlreadyLoggedInException : Exception
{
public UserAlreadyLoggedInException(string message) : base(message)
{
Console.WriteLine("Here");
}
}
Now, I know that base class constructor runs before derived class constructor. But when I run the above code the output comes out to be
Here
Unhandled Exception:Testing.UserAlreadyLoggedInException:Hello.
How come "Here" is printed before Unhandled.....?
You first have to create the exception, before you can be thrown.
Creation of the exception instance initiated by new UserAlreadyLoggedInException;
UserAlreadyLoggedInException constructor called;
Call to Console.WriteLine inside constructor;
Constructor done;
Throwing of the newly created exception instance;
The exception isn't handled, thus the application error handler writes the error to the console.
Why don't you try this:
static class Program
{
static void Main()
{
throw new UserAlreadyLoggedInException("Hello");
}
}
class LoginException : Exception
{
public LoginException(string message) : base(message)
{
Console.WriteLine("least derived class");
}
}
class UserAlreadyLoggedInException : LoginException
{
public UserAlreadyLoggedInException(string message) : base(message)
{
Console.WriteLine("most derived class");
}
}
You can also try writing your Main method like this:
static void Main()
{
var ualie = new UserAlreadyLoggedInException("Hello");
Console.WriteLine("nothing bad has happened yet; nothing thrown yet");
throw ualie;
}
So constructing an Exception instance with the new keyword does not "raise" or "throw" an exception. You need throw for that. The throw statement works by first evaluating the expression that comes after the throw keyword. The result of that evaluation will be a reference to an exception instance. After evaluating the expression, throw "throws" the exception referred by the value of the expression.
Your misunderstanding is that the Exception "explodes" as soon as the instance constructor to System.Exception runs. That is not the case.
If you add a try/catch of your own the program flow becomes more apparent. Note that Exception's constructor does not write anything it just stores the message string for later use.
class Program
{
static void Main(string[] args)
{
try
{
throw new UserAlreadyLoggedInException("Hello");
}
catch (Exception e)
{
Console.WriteLine("My handled exception: {0}", e.Message);
}
}
}
public class UserAlreadyLoggedInException : Exception
{
public UserAlreadyLoggedInException(string message) : base(message)
{
Console.WriteLine("Here");
}
}
The exception is printed to the console after it has been instantiated and thrown.
The instantiation prints "Here", then the runtime catches it and prints the "Unhandled Exception:" ToString() representation.

Is there a way to mark code as non-threadsafe in C#?

Im trying to hunt down a race condition, and I come across a lot of suspecious functions. Most of them are not allowed to be called from two threads at the same time, but its hard to make sure they don't.
Is there some keyword to instruct the runtime to throw an exception as soon as a function is executing in parallel? I know I sometimes get an exception when another thread modifies a collection which im enumerating, but are safeguards like that enough to rely on?
The runtime can halt execution using the lock instruction, so all I need is a lock which throws an error.
You can use Monitor.TryEnter for this:
bool entered = !Monitor.TryEnter(someLockObject);
try
{
if (!entered)
throw Exception("Multi-thread call!");
// Actual code
}
finally
{
if (entered)
{
Monitor.Exit(someLockObject);
}
}
And it would be good to wrap that code in its own class:
public sealed class MultiThreadProtector : IDisposable
{
private object syncRoot;
public MultiThreadProtector(object syncRoot)
{
this.syncRoot = syncRoot;
if (!Monitor.TryEnter(syncRoot))
{
throw new Exception("Failure!");
}
}
public void Dispose()
{
Monitor.Exit(this.syncRoot);
}
}
This way you can execute it as follows:
using (new MultiThreadProtector(someLockObject))
{
// protected code.
}

Need to break after exception is handled

I have built an app in C#, where I have to break just after an exception is caught. I used return, but it returned to the module which called this module and continued execution. What should be done?
My code looks likes this:
class a
{
b bee=new b{};
bee.read(name);
bee.write(name);// don want this to get executed if exception is thrown
}
class b
{
read(string name)
{
try{}
catch
{
//caught;
//what should be put here so that it just stops after dialog
// box is shown without moving to the write method?
}
write(string name) {}
}
}
Your code sample is incorrect, but let's assume that you have a method with this code inside:
void M()
{
b bee=new b();
bee.read(name);
bee.write(name);// don want this to get executed if exception is thrown
}
If so, you have to catch exceptions in this method, not in read method. Like so:
void M()
{
try {
b bee=new b();
bee.read(name);
bee.write(name);// don want this to get executed if exception is thrown
}
catch(Exception e) {
// Proper error handling
}
}
In read method you should not suppress exceptions. Either don't catch them at all or rethrow them (or better yet, throw a new exception with the old one being its InnerExeption).
If you handle exceptions in method M this way, he line bee.write(name) won't be executed if an exception occurs somewhere inside bee.read(name).
Let the exception bubble up to the calling method:
class A {
public void Method() {
B bee = new B{};
try {
bee.Read(name);
bee.Write(name);
} catch(Exception ex) {
// handle exception if needed
}
}
}
class B {
public void Read(string name) {
try{
...
} catch(Exception ex) {
// handle exception if needed
throw;
}
}
public void Write(string name) {
}
}
Note: You should catch a more specific exception class if posible, instead of catching the base class Exception. The catch syntax without an excpetion parameter is obsolete.
you can do this as follows
class a
{
b bee = new b();
try
{
bee.read(name);
bee.write(name);
}
catch(Exception ex)
{
//handle error here
}
}
class b
{
//These are your method implementations without catching the exceptions in b
read
write
}
If you catch the exception in the method then you won't have any way of knowing the exceution state of the method without hangind some kind of error status off the method. Whether that is a boolean return or an error code that is accesible in b.
Why not have the read method return a value that means something to the caller? so the caller inspects the return from read and if it's (for example) null it doesn't call write. Alternatively your read method could return an enum value that tells the caller the condition with which the read method exited.
As another option your caller could implement an interface with a doNotProceed method, then pass itself to the read method. On exception read calls caller.doNotProceed, setting an internal variable within the caller object and this tells it to not proceed to write.
You have plenty of options
You can use return statement or re throw the error and put another a parent try catch , but its better you restructure your code.

Categories