Object not disposing when throw used in using statement, c# [duplicate] - c#

This question already has an answer here:
Why Dispose is not called even with using-statement?
(1 answer)
Closed 5 months ago.
Below my code example. Why tom.Dispose() method doesn't called (I don't see message in console) despite it is in using block?
class Program
{
static void Main()
{
using (Person tom = new Person("Tom"))
{
Console.WriteLine($"Name: {tom.Name}");
try
{
dynamic result = new ExpandoObject();
result.d = 1;
Console.WriteLine(result.a.b);
}
catch (Exception)
{
throw;
}
}
}
}
public class Person : IDisposable
{
public string Name { get; }
public Person(string name) => Name = name;
public void Dispose() => Console.WriteLine($"{Name} has been disposed");
}
upd: if I modify catch block to below, tom.Dispose() is called
catch (Exception)
{
if (tom != null)
tom.Dispose();
throw;
}

The object gets disposed properly. The way the code is written, the exception is rethrown and never handled and the application terminates before it has a chance to write to the console.
This snippet does print the message:
static void Main()
{
try
{
using (Person tom = new Person("Tom"))
{
Console.WriteLine($"Name: {tom.Name}");
dynamic result = new ExpandoObject();
result.d = 1;
Console.WriteLine(result.a.b);
}
}
catch(Exception){}
}
This produces :
Name: Tom
Tom has been disposed

Related

How can I correctly throw an exception when a class is being destroyed?

I'd like to employ the IDisposable pattern in my C# class so I can wrap it in a 'using block' later on. My issue is that, when the class is getting disposed, I want to be able to throw an exception sometimes if a specific condition isn't met.
I know I can technically throw an exception in either the Dispose method or the class's destruction but it seems, this is discouraged, as per this Microsoft post
class PersonListBuilder : IDisposable
{
private readonly List<Person> _persons = new List<Person>();
public PersonListBuilder SetName(string name)
{
_name = name;
return this;
}
public PersonListBuilder SetAge(int age)
{
_age = age;
return this;
}
public PersonListBuilder Push()
{
_persons.Add(new Person
{
Name = _name,
Age = _age,
}
PrepareForNewPerson();
}
public List<Person> Build()
{
//Because of other implementation details, I cannot call method 'ThrowExceptionIfUnPushedPersonExists' here
return _persons;
}
private void PrepareForNewPerson()
{
_name = string.Empty;
_age = default;
}
private void ThrowExceptionIfUnPushedPersonExists()
{
if(!string.IsNullOrEmpty(_name) || age != 0)
{
throw new Exception("Seems there is an unpushed person");
}
}
public void Dispose()
{
//Call below method here is discouraged :(
ThrowExceptionIfUnPushedPersonExists()
}
}
class PersonBuilderConsumer
{
public void MakePersons()
{
//What I'd like to do
try
{
using(var personListBuilder = new PersonListBuilder())
{
//We won't call the 'Push' method below, so an exception will be throw
var persons = personListBuilder.SetName("Jane")
.SetAge(36)
.Build();
}
}
catch(Exception e)
{
// unpushed person exception should get thrown then handled here
}
}
}
Ideally, I would like to use the code as is show in the sample, but again, as per this Microsoft post, the 'Dispose' method, is on the list of places where throwing of exceptions is discouraged. Is there a better way to have my builder return expected result when input is valid but fail if input is wrong?
I could of course call make the method 'ThrowExceptionIfUnPushedPersonExists' public and call it myself right before the end of the 'using block', but then am worried that I may forget to do so, which would make the Builder 'untrustworthy'.

Exception Handling in C# Without Throwing It

Hey everybody I am just getting into C# and was going over exception handling. I am trying to find a way to trigger my custom exception without actually throwing it. It seems clunky to write throw new "custom exception" every time I want to error handle. With the throw line commented out my exception never gets triggered and I know that is because I am originally setting the object to null but can't find a way around this.
public class Person
{
public Person(String name)
{
Name = name;
}
public String Name { get; set; }
}
public class PersonException : Exception
{
public PersonException() : base() {}
}
public class Program
{
static void Main(string[] args)
{
Person p = null;
try
{
p = new Person("kim");
//throw new PersonException();
}
catch (PersonException z) when(p.Name == "kim")
{
Console.WriteLine(z.Message);
}
}
}
}
I don't think you fully understand the concept of exceptions (or your description does not make sense).
Your code will only ever enter the later part of the code below once an exception has occurred. You are not throwing an exception and likewise your code will not result in an exception. Seeing as no exception is occurring and you aren't manually throwing an exception I see no reason why it should ever enter the catch statement. The whole idea is to catch the error, which occasionally you might have to throw.
try {
// your code here
}
catch (Exception ex) {
// here we catch a generic exception
}
...even this wouldn't activate your catch clause because attempting to cast an invalid string to an int would throw an error different to your custom PersonException.
public class Person
{
public Person(String name)
{
Name = name;
}
public String Name { get; set; }
public int Age { get; set; }
}
try
{
p = new Person("kim");
p.Age = Convert.ToInt32("NOT AN INT");
}
catch (PersonException z) when(p.Name == "kim")
{
Console.WriteLine(z.Message);
}
Exceptions are for exceptional circumstances. You just need an if or switch block to check if the person's name is "kim".
All of the things already said by others apply and are good advice and I won't repeat them, but I think that what you're trying to do is better expressed as:
public class Program
{
static void Main(string[] args)
{
Person p = null;
try
{
p = new Person("kim");
if(p.Name == "kim")
{
throw new PersonException();
}
}
catch (PersonException z)
{
Console.WriteLine(z.Message);
}
}
}
...So you only throw the exception when you have the error situation, rather than only catch it in certain situations.

Catch derived class Exceptions in base class with different methods and arguments

I'm trying to make something like base "exception handler" thing. So this base class will try-catch exceptions when any method (with any number of parameters) in derived class gets invoked. I'm not good in describing this with words, so here is the scenario:
public abstract BaseClass
{
Exception _ex;
public Exception LastKnownException
{
get
{
return this._ex;
}
}
//...
//what do I do here to assign the value of above property when some random exception occur in derived class?
//...
//The closest I can get...
public void RunMethod(Action method)
{
try
{
method.Invoke();
}
catch (Exception ex)
{
this._ex = ex;
}
}
}
public class DerivedClass : BaseClass
{
public void DoRandomMethod(int couldBeOfAnyTypeHere, bool andIndefiniteNumberOfThese)
{
bool result = false;
var someObject = new OtherClass(couldBeOfAnyTypeHere, out andIndefiniteNumberOfThese);
someObject.DoInternalWork(result); // <-- here is where I need the base class to take care if any exception should occur
}
public int AnotherMethod(int? id)
{
if (!id.HasValue)
id = Convert.ToInt32(Session["client_id"]);
var someOtherObject = new OtherClassB(id.Value);
return someOtherObject.CheckSomething(); // <-- and catch possible exceptions for this one too
}
//The closest I can get... (see base class implementation)
public List<RandomClass> GetSomeListBy(int id)
{
RunMethod(() =>
string[] whateverArgs = new[] { "is", "this", "even", "possible?" };
YetAnotherStaticClass.GetInstance().ExecuteErrorProneMethod(whateverArgs); // <-- Then when something breaks here, the LastKnownException will have something
);
}
}
public class TransactionController : Controller
{
public ActionResult ShowSomething()
{
var dc = new DerivedClass();
dc.DoRandomMethod(30, true);
if (dc.LastKnownException != null)
{
//optionally do something here
return RedirectToAction("BadRequest", "Error", new { ex = dc.LastKnownException });
}
else
{
return View();
}
}
}
EDIT: My simple approach will work, only, I don't want to have to wrap all methods with this lambda-driven RunMethod() method all the time -- I need the base class to somehow intercept any incoming exception and return the Exception object to the derived class without throwing the error.
Any ideas would be greatly appreciated. And thanks in advance!
I think you should consider using the event System.AppDomain.UnhandledException
This event will be raised whenever an exception occurs that is not handled.
As you don't clutter your code with the possibilities of exception, your code will be much better readable. Besides it would give derived classes the opportunity to catch exceptions if they expect ones, without interfering with your automatic exception catcher.
Your design is such, that if someone calls several functions of your derived class and then checks if there are any exceptions the caller wouldn't know which function caused the exception. I assume that your caller is not really interested in which function causes the exception. This is usually the case if you only want to log exception until someone investigates them.
If that is the case consider doing something like the following:
static void Main(string[] args)
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
}
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
var ex = e.ExceptionObject as Exception;
if (ex != null)
logger.LogException(ex);
// TODO: decide whether to continue or exit.
}
If you really want to do this only for your abstract base class
public abstract BaseClass
{
private List<Exception> unhandledExceptions = new List<Exception>();
protected BaseClass()
{
AppDomain.CurrentDomain.UnhandledException += UnhandledException;
}
private void UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
var ex = e.ExceptionObject as Exception;
if (ex != null)
this.UnhandledExceptions.Add(ex);
}
public List<Exception> LastKnownExceptions
{
get { return this.unhandledExceptions; }
}
I had a similar requirement for catching exceptions, but used a specific implementation (i.e. not an abstract class) to encapsulate the handling of errors.
Please note this takes in an argument for any expected exceptions (params Type[] catchableExceptionTypes), but of course you can modify to suit your own requirements.
public class ExceptionHandler
{
// exposes the last caught exception
public Exception CaughtException { get; private set; }
// allows a quick check to see if an exception was caught
// e.g. if (ExceptionHandler.HasCaughtException) {... do something...}
public bool HasCaughtException { get; private set; }
// perform an action and catch any expected exceptions
public void TryAction(Action action, params Type[] catchableExceptionTypes)
{
Reset();
try
{
action();
}
catch (Exception exception)
{
if (ExceptionIsCatchable(exception, catchableExceptionTypes))
{
return;
}
throw;
}
}
// perform a function and catch any expected exceptions
// if an exception is caught, this returns null
public T TryFunction<T>(Func<T> function, params Type[] catchableExceptionTypes) where T : class
{
Reset();
try
{
return function();
}
catch (Exception exception)
{
if (ExceptionIsCatchable(exception, catchableExceptionTypes))
{
return null;
}
throw;
}
}
bool ExceptionIsCatchable(Exception caughtException, params Type[] catchableExceptionTypes)
{
for (var i = 0; i < catchableExceptionTypes.Length; i++)
{
var catchableExceptionType = catchableExceptionTypes[i];
if (!IsAssignableFrom(caughtException, catchableExceptionType)) continue;
CaughtException = caughtException;
HasCaughtException = true;
return true;
}
return false;
}
static bool IsAssignableFrom(Exception exception, Type type)
{
if (exception.GetType() == type) return true;
var baseType = exception.GetType().BaseType;
while (baseType != null)
{
if (baseType == type) return true;
baseType = baseType.BaseType;
}
return false;
}
void Reset()
{
CaughtException = null;
HasCaughtException = false;
}
}

Avoid Try Catch Stements with custom ErrorHandler class - C#

I have a class which exposes some functionality,
and I want to ensure exceptions will be handled by a custom ErrorHandler class.
Currently I can achieve this by a try / catch statement per each method, and process the exception by the error handler there.
My question is if there is a better way / design pattern to do it.
Code:
public class BasicErrorHandler
{
public void ProcessException(Exception ex)
{
//Does error handling stuff
}
}
public class Manager
{
BasicErrorHandler _errorHandler;
public Manager()
{
_errorHandler = new BasicErrorHandler();
}
public void MethodA()
{
try
{
//Does Something
}
catch(Exception ex)
{
_errorHandler.ProcessException(ex);
}
}
public void MethodB()
{
try
{
//Does Something Else
}
catch(Exception ex)
{
_errorHandler.ProcessException(ex);
}
}
}
In keeping with DRY principles, you could just wrap your try...catch logic into into own method which takes a predicate of the actual work to do:
public class Manager
{
BasicErrorHandler _errorHandler;
public Manager()
{
_errorHandler = new BasicErrorHandler();
}
public void MethodA()
{
DoWork( () => {
// do something interesting here
});
}
public void MethodB()
{
DoWork( () => {
// do something else interesting here
});
}
private void DoWork(Action action)
{
try
{
action();
}
catch(Exception ex)
{
_errorHandler.ProcessException(ex);
}
}
}
I've crafted this quickly and without thinking too much in the implications, but if you want to avoid all the try/catch blocks, you could do something like:
public class BasicErrorHandler
{
public void ProcessException(Exception ex)
{
//Does error handling stuff
}
public void Do(Action act)
{
try
{
act();
}
catch(Exception ex)
{
ProcessException(ex);
}
}
}
And then use it like:
public class Manager
{
BasicErrorHandler _errorHandler;
public Manager()
{
_errorHandler = new BasicErrorHandler();
}
public void MethodA()
{
_errorHandler.Do(() => {
//Does Something
});
}
public void MethodB()
{
_errorHandler.Do(() => {
//Does Something Else
});
}
}
Design patterns are there to solve a problem. Which problem are you trying to solve? What is wrong with the Try Catch blocks?
Only thing I can imagine is you want to have more clean code. Some answers suggest a helper method with an action. Given the helper methods that encapsulate a delegate: Do consider the impact on your stack trace and debugging sessions using these delegates. It might make logging etc more hard to understand.
If your intend is to do separation of concern, I would say If you can't handle it, just don't catch the exception. Let the class invoking the method handle it. If you insist to have a handler in your class, I would suggest Inversion of Control. That way, your class is not in control of determining which class should handle its exceptions.
Rx .net is for You. Advanced error handling gives You the ability to highly customize Your error handling. Check out the pages about that.
For example:
var source = new Subject<int>();
var result = source.Catch<int, TimeoutException>(tx=>Observable.Return(-1));
result.Dump("Catch");
source.OnNext(1);
source.OnNext(2);
source.OnError(new ArgumentException("Fail!"));
You'll get the following output:
Catch-->1
Catch-->2
Catch failed-->Fail!
The number of retries, the handling of how much time a method can take, everything can be configured.
The following is an Aspect oriented method of soling the problem, this makes use of PostSharp to do the weaving.
[Serializable]
public class HandleExceptionsAttribute : OnExceptionAspect {
/// <summary>
/// Initializes a new instance of the <see cref="HandleExceptionsAttribute"/> class.
/// </summary>
public HandleExceptionsAttribute() {
AspectPriority = 1;
}
public override void OnException(MethodExecutionArgs args) {
//Suppress the current transaction to ensure exception is not rolled back
using (var s = new TransactionScope(TransactionScopeOption.Suppress)) {
//Log exception
using (var exceptionLogContext = new ExceptionLogContext()) {
exceptionLogContext.Set<ExceptionLogEntry>().Add(new ExceptionLogEntry(args.Exception));
exceptionLogContext.SaveChanges();
}
}
}
}
[HandleExceptions]
public class YourClass {
}

Get thrown exception in finally block

Is there a way, how to get currently thrown exception (if exists)?
I would like reduce amount of code and apply some reuse for task looks like:
Exception thrownException = null;
try {
// some code with 3rd party classes, which can throw unexpected exceptions
}
catch( Exception exc ) {
thrownException = exc;
LogException( exc );
}
finally {
if ( null == thrownException ) {
// some code
}
else {
// some code
}
}
and replace it with this code:
using( ExceptionHelper.LogException() ) {
// some code with 3rd party classes, which can throw unexpected exceptions
}
using( new ExceptionHelper { ExceptionAction = ()=> /*some cleaning code*/ } ) {
// some code with 3rd party classes, which can throw unexpected exceptions
}
public class ExceptiohHelper : IDisposable {
public static ExceptionHelper LogException() {
return new ExceptionHelper();
}
public Action SuccessfulAction {get; set;}
public Action ExceptionAction {get; set;}
public void Dispose() {
Action action;
Exception thrownException = TheMethodIDontKnow();
if ( null != thrownException ) {
LogException( thrownException );
action = this.ExceptionAction;
}
else {
action = this.SuccessfulAction;
}
if ( null != action ) {
action();
}
}
}
Is this scenario posible?
Thanks
The idea is that you handle exceptions in the catch block...
That said, Exception is a reference type, so you can always declare an Exception variable outside the try scope...
Exception dontDoThis;
try
{
foo.DoSomething();
}
catch(Exception e)
{
dontDoThis = e;
}
finally
{
// use dontDoThis...
}
What do you think about the following. Instead of looking at the problem as "How to get the last exception?", what if you change it to, "How do I run some piece of code with some more control?"
For example:
Instead of an ExceptionHelper you could have an ActionRunner.
public class ActionRunner
{
public Action AttemptAction { get; set; }
public Action SuccessfulAction { get; set; }
public Action ExceptionAction { get; set; }
public void RunAction()
{
try
{
AttemptAction();
SuccessfulAction();
}
catch (Exception ex)
{
LogException(ex);
ExceptionAction();
}
}
private void LogException(Exception thrownException) { /* log here... */ }
}
It would at least give you some reuse of the SuccessfulAction and ExceptionAction assuming only the AttemptAction varies between calls.
var actionRunner = new ActionRunner
{
AttemptAction = () =>
{
Console.WriteLine("Going to throw...");
throw new Exception("Just throwing");
},
ExceptionAction = () => Console.WriteLine("ExceptionAction"),
SuccessfulAction = () => Console.WriteLine("SuccessfulAction"),
};
actionRunner.RunAction();
actionRunner.AttemptAction = () => Console.WriteLine("Running some other code...");
actionRunner.RunAction();
If you are looking to catch unexpected exceptions you should be handling the UnhandledException. You should only catch exceptions at lower levels that you intend handle (not just to log), otherwise you should let them bubble up and be caught at a higher level, or as I mentioned before in the UnhandledException method.

Categories

Resources