Using instructions does not work correctly

My class named S looks like this:

public class S : IDisposable { public void Dispose() { // some code } public void f() { throw new Exception("exception"); } } 

When I use the using statement, the f () method does not call the s.Dispose () method. I thought that it should call the Dispose method, even if it is an exception. This is what I read on MSDN: "The using statement ensures that Dispose is called even if an exception occurs when you call methods on an object." Did I miss something?

 using (S s = new S()) { sf(); } 

Calling sf () terminates my program without deleting my s object. I think I do not need to use try / catch, because using an instruction should do this for me.

+6
source share
3 answers

The problem may be that you are running the code in the debugger. This means that any code occurs after an unhandled exception is thrown because the debugger stops at that point.

If you run the test script from the debugger, then the Dispose() method is called when the runtime clears the mess. Put some marker code in the Dispose () method, which will give you a visible sign that Dipose calls: for example, create a file in some available folders namesd DisposedHasRun.yeah (note that output to the console or MessageBox not an option, because the application quits due to an unhandled exception). When you run the test case outside the debugger, you will see that the file was created.

However, there are times when Dispose will not be called (and finally ). For example, StackOverflow due to infinite recursion will not call Dispose() , because the runtime will cause the application to exit the system as soon as possible. ( ThreadAbortException I think it will behave the same)

+3
source

Did I miss something?

Operator

A using translates to a try ... finally .

According to try ... finally reference to C # ,

The processed exception guarantees the execution of the associated finally block. However, if the exception is unhandled, the execution of the finally block depends on how the unlock release operation is started. This, in turn, depends on how your computer is configured.

So, you have something missing: the finally block (and therefore the Dispose call in the using statement) is not guaranteed under any circumstances, including in your circumstances, an unhandled exception.

Next is the page:

Usually, when an unhandled exception terminates the application, whether or not the finally block is executed is not important. However, if you have instructions in a finally block that should be run even in this situation, one solution is to add a catch block to try-finally . Alternatively, you can catch an exception that can be thrown in the try block of a try-finally statement above the call stack. That is, you can catch an exception in a method that calls a method that contains a try-finally statement or a method that calls this method, or in any way on the call stack. If the exception is not caught, the execution of the finally block depends on whether the operating system decides to initiate the operation to cancel the exception.

I would be happier if I could find the links in the C # spec. Unfortunately, my reading of ยง8.9.5 is that even an unhandled exception should cause all finally statements on the way to execute the stack.

+5
source

in your comment your statement that you use this code at your disposal

 System.IO.FileStream fs = new System.IO.FileStream(@"C:\exception.txt", System.IO.FileMode.CreateNew); fs.Write(Encoding.Unicode.GetBytes("object disposed"), 0, Encoding.Unicode.GetBytes("object disposed").Length); fs.Close(); 

if you read how FileStream FileMode work;

Createnew

Indicates that the operating system should create a new file. This permission is required by FileIOPermissionAccess.Write. If the file already exists, an IOException is thrown.

I am sure you selected an exception because the file already exists.

check if the file exists, then use System.IO.FileMode.Append if necessary

-1
source

Source: https://habr.com/ru/post/975782/


All Articles