|
PIEBALDconsult wrote: buchstaben wrote:
In effect, extension methods make it possible
make it appear possible, when in fact it isn't.
that's just what c# 3.0 specification says.
|
|
|
|
|
Hello everyone,
I understand there is no need to call Dispose explicitly when dealing with StreamReader/StreamWriter object instances since GC will take care of it in Finalizer method.
My question is, I want to know the benefits and potential issues of using "using" statement to deal with StreamReader/StreamWriter.
thanks in advance,
George
|
|
|
|
|
George_George wrote: I understand there is no need to call Dispose explicitly when dealing with StreamReader/StreamWriter object instances
you may not need to, but I would suggest its still good practice.
I always use using when dealing with stream readers/writers
using (StreamReader sr = new StreamReader(someStream))
{
...
}
|
|
|
|
|
Thanks J4amieC,
What is the benefit?
regards,
George
|
|
|
|
|
George_George wrote: What is the benefit?
Deterministic disposal. When the using statement ends, it will call Dispose(), it can reclaim the memory immediately and suppress GCs finalization.
|
|
|
|
|
|
Never leave it to the GC to take care of your cleanup. It is non-deterministic. You should take proper care to dispose of your resources.
The managed resource is automatically disposed when the control exits the using block, so you don't need to do it yourself. It is also disposed if your code exits abnormally (exception is thrown, etc).
Cheers,
Vikram.
The hands that help are holier than the lips that pray.
|
|
|
|
|
Thanks Vikram,
My current situation is, I am writing an Http Service and handle requests from client by using StreamReader in some function to read from InputStream of Http request.
My previous consideration is, even if GC is not worked determistic, or there will be exception, when the Http Service stops (process stops or terminations), all resources like native handle wrapped by StreamReader could be released automatically.
What is the benefit of using "using" statement?
regards,
George
|
|
|
|
|
George_George wrote: when the Http Service stops (process stops or terminations), all resources like native handle wrapped by StreamReader could be released automatically.
What is the benefit of using "using" statement?
When the process stops, all the native handles will be released. But if this application is expected to run for a long time, restarting it frequently to release the handles is not a good idea. using block ensures the call to Dispose() method when you come out of the block. See the following code
using(Stream str = new FileStream(..))
{
}
Stream str = null;
try
{
str = new FileStream(..);
}
finally
{
if(str != null)
((IDisposable)str).Dispose();
} Both does the same, using is a shortcut for this pattern.
Benefit will be instant memory reclaiming than waiting for GC, once you finish using the disposable instance.
|
|
|
|
|
Thanks N a v a n e e t h,
In the C# compiler expanded code, no catch block? Just a finally block?
regards,
George
|
|
|
|
|
George_George wrote: In the C# compiler expanded code, no catch block? Just a finally block?
I am not getting you
|
|
|
|
|
Thanks N a v a n e e t h,
I have found one setback of using block. It will not handle any exception in Dispose method. And if there are any exception in Dispose method, the original exception in using block will be missing.
Here is my test code. Any comments?
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Xml;
class Test
{
class MyException : ApplicationException
{
public MyException (string message)
: base(message)
{
}
}
class MyObject : IDisposable
{
public virtual void Dispose()
{
Console.WriteLine("Disposed ");
throw new MyException("Disposed exception. ");
}
}
public static void Main()
{
try
{
using (MyObject myobj = new MyObject())
{
throw new MyException("Hello World");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
regards,
George
|
|
|
|
|
using is a syntactic shortcut for try/finally pattern. I rewrote your code with try/finally for making this clear
try
{
MyObject myobj = new MyObject();
try
{
throw new MyException("Hello World");
}
finally
{
myobj.Dispose();
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
} Here it will throw MyException("Hello World") first - since we haven't defined any catch statements, corresponding finally will be executed. In this case finally also throwing error and the catch block will handle the latest exception which is disposed exception here.
The dispose pattern suggests to handle all possible exception and not to throw exceptions in the Dispose method. So you won't feel this problem anymore.
|
|
|
|
|
Thanks N a v a n e e t h!
It is in theory that the information of MyException("Hello World") is missing when there is exception in Dispose, right?
regards,
George
|
|
|
|
|
George_George wrote: It is in theory that the information of MyException("Hello World") is missing when there is exception in Dispose, right?
Not exactly. You can catch the exception before disposing. The behavior you are seeing is how catch works. It catches latest exceptions. As you know finally executes even if there is an error. So you are generating one more exception inside the finally. So the latest exception is the one generated inside the finally block and it will be handled by the next catch statement.
|
|
|
|
|
Thanks N a v a n e e t h,
You always have great ideas.
Your solution works perfect when there is exception and we are in finally block because of the exception. The issue I can see from this solution is, when executing in finally block, there may be no exception, right? How can you write a common finally block, to handle exception at first, then Dispose?
regards,
George
|
|
|
|
|
George_George wrote: when there is exception and we are in finally block because of the exception
We are in finally block not because of exception. Finally block will be executed always.
George_George wrote: How can you write a common finally block, to handle exception at first, then Dispose?
Finally block can't handle exceptions, it is caught by a catch block. I am not getting your point here. Can you explain it little bit more ? Are you asking how to handle exceptions in the finally ?
|
|
|
|
|
Thanks N a v a n e e t h,
Sorry for my bad English, here is my code posted before. And it has the issue of MyException ("Hello World") will be missing if there is exception in Dispose method.
You have a great solution to solve it by -- "You can catch the exception before disposing". It sounds great but I do not know how to apply this idea in my code sample. Could you help to show your code please?
http://www.codeproject.com/script/Forums/View.aspx?fid=1649&msg=2568610[^]
regards,
George
|
|
|
|
|
okay. Here is what you can do
public static void Main()
{
try
{
using (MyObject myobj = new MyObject())
{
try{
throw new MyException("Hello World");
}
catch(MyException)
{
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
} In this case, exception is handled before object is disposing. This is pretty straight forward.
Hope it's clear
|
|
|
|
|
Thanks N a v a n e e t h,
Your solution is good enough.
I have some further ideas. In your pattern there will be additional overhead, since there will be 3 try blocks, two explicit ones and one implicit one.
Try block will add additional overhead in my knowledge to runtime to stack manipulation.
So, if not using "using" block, we only need two try block, one to wrap normal operations and one to wrap Dispose in finally. So, in this way, using block has no advantage -- it uses 3 using blocks and we can only use 2 if write manually.
Any comments?
regards,
George
|
|
|
|
|
You are right. It can be written as you said.
|
|
|
|
|
Great N a v a n e e t h!
Question answered.
regards,
George
|
|
|
|
|
Wait just a freakin minute. Back when I was arguing against using C# and .Net, everybody was quick to point out the automatic-ness of memory handling, specifically mentioning thew GC.
Now, here we are a few years down the road, and I see people saying not to rely on the GC.
So which is it - a good thing, or a bad thing?
Personally, I avoid "using" statements because I think they obfuscate the intent of code.
"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997 ----- "...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001
|
|
|
|
|
John Simmons / outlaw programmer wrote: So which is it - a good thing, or a bad thing?
Having a GC is good because it reduces the problem of leaks, etc, but it would be foolish to rely on it to do *all* your cleanup.
Cheers,
Vikram.
The hands that help are holier than the lips that pray.
|
|
|
|
|
I agree, Vikram.
regards,
George
|
|
|
|