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
TheCPUWizard
May 20th, 2008, 06:55 AM
George,
If you do not understand the difference between Dispose() and Finalize() and when each is appropriate, then you really need to go back to the books for a few weeks, and stop coding immediately.
JonnyPoet
May 20th, 2008, 07:03 AM
...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....
George, :eek:
there is a main difference between Closing a stream and disposing Streams are limited resources and you should close them when finished your current job.
So you can use Using or finlaize to get this handled and you havn't to worry about open streams e.g when an exception throws you out of your actual process.
George2
May 20th, 2008, 07:04 AM
Sorry TheCPUWizard,
I think I understand the basic theory. :wave: ;)
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 each 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?
George,
If you do not understand the difference between Dispose() and Finalize() and when each is appropriate, then you really need to go back to the books for a few weeks, and stop coding immediately.
regards,
George
George2
May 20th, 2008, 07:09 AM
Thanks JonnyPoet,
1.
George, :eek:
there is a main difference between Closing a stream and disposing Streams are limited resources and you should close them when finished your current job.
Please correct me if I am wrong. I have used reflector before, and Close method of Stream related classes will call Dispose method (just a wrapper to call Dispose), and this is a general Dispose pattern. Why do you think calling Dispose is different from calling Close -- "there is a main difference between Closing a stream and disposing"? I think it is the same.
2.
So you can use Using or finlaize to get this handled and you havn't to worry about open streams e.g when an exception throws you out of your actual process.
Good point. If there is exception, and in both exception handler and finally block, I do not call Close/Dispose explicitly, will Dispose/Close be called automatically during exception? Or we have to wait for GC to call Finalize?
regards,
George
MadHatter
May 20th, 2008, 07:32 AM
the general rule (not specific to this case) is: if it implements IDisposable, call dispose as soon as you're done w/ it.
placing it in a using statement is a short hand notation. the IL produced by it places the usage in try catch finally statements that close and dispose of the object, and ensures that any exception that's thrown during use will not affect the disposal process of the stream.
there should never be a need to see how a class is implemented before choosing how to deal with it, deal with it based on its documented API because internals are not guaranteed to remain the same in successive versions of the framework.
ALSO: DON'T POST MULTIPLE TIMES TO ANSWER DIFFERENT PEOPLE, DO IT IN THE SAME POST!!!
eclipsed4utoo
May 20th, 2008, 08:16 AM
my rule of thumb is similar to MadHatter, if it contains Dispose, then use it. it's there for a reason, right?
George2
May 20th, 2008, 08:26 AM
Thanks eclipsed4utoo and MadHatter!
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.
Even though I am not using "using" and since the traffic is low, I do not meet with any issues.
I would like to learn from you and let you anticipate what issues I will meet with if I do not use "using" in my situation?
my rule of thumb is similar to MadHatter, if it contains Dispose, then use it. it's there for a reason, right?
regards,
George
eclipsed4utoo
May 20th, 2008, 09:14 AM
As somebody who runs their own website from their home PC(Windows XP Pro) and the website does HTTP requests, I started running into alot of issues because I wasn't disposing of the objects when I was done. I was consistently having a problem where I would get the IIS message "too many users are connected". I think this was happening because the connections where staying open, even though I called Close(). After optimizing the code to dispose of all of the objects when completed, I don't have the problem anymore.
C#, through the .NET Framework common language runtime (CLR), automatically releases the memory used to store objects that are no longer required. The release of memory is non-deterministic; memory is released whenever the CLR decides to perform garbage collection. However, it is usually best to release limited resources such as file handles and network connections as quickly as possible.
George2
May 20th, 2008, 09:26 AM
Thanks eclipsed4utoo,
1.
I think in your situation of "too many users are connected" is not because your code has bug which does not free handle, but because of GC does not free handles immediately?
2.
I think using Dispose call explicitly will solve this issue. :-)
As somebody who runs their own website from their home PC(Windows XP Pro) and the website does HTTP requests, I started running into alot of issues because I wasn't disposing of the objects when I was done. I was consistently having a problem where I would get the IIS message "too many users are connected". I think this was happening because the connections where staying open, even though I called Close(). After optimizing the code to dispose of all of the objects when completed, I don't have the problem anymore.
Stream readers and writers are decorators around a "stream" object. stream objects are an abstraction around file, memory, and network IO's.
HTTP is a protocol and the request you're processing at some point is a set of bytes read from a socket (at a lower level). the request object's stream decorates the socket class to allow for a common "stream" like interface around sending and receiving from the socket.
if you think of the socket and hypter text transfer protocol for a second, each client request is a stateless request wherein the client opens a socket connection to the server, sends a request, waits for a response, then disconnects. server side, all of that logic is implemented for you, so ultimately your decorator reader / writer is not responsible for the underlying connection and resources, it only uses it to do what it does.
where you'll get into trouble is when YOU are the one managing the client connection, state, and lifetime, and you don't explicitly close and dispose of the connection (which closes the underlying socket). the client can terminate the connection, but your server socket will throw an exception and unless you handle that, could leave you in a bad state...
so, even if you cannot understand why... it's always a best practice to dispose of IDisposable objects when you are done, and not leave it up to the GC as to when to dispose or finalize of the object. calling dispose allows the GC to collect the items that would otherwise age before being collected, so it helps keep things tidy and puts less work on the heuristics of determining what to clean up and what to let set.
eclipsed4utoo
May 20th, 2008, 10:06 AM
Thanks eclipsed4utoo,
1.
I think in your situation of "too many users are connected" is not because your code has bug which does not free handle, but because of GC does not free handles immediately?
2.
I think using Dispose call explicitly will solve this issue. :-)
regards,
George
1. The GC is almost never immediate. It's a periodic process.
2. That's the "optimizing" that I did.
TheCPUWizard
May 20th, 2008, 10:11 AM
1. The GC is almost never immediate. It's a periodic process.
2. That's the "optimizing" that I did.
It is NOT a periodic process. It is a demand based process when there is memory pressure at the time of a NEW allocation.
If you dont do new allocations, GC will NEVER execute. If there is no memory pressure GC will NEVER execute.
eclipsed4utoo
May 20th, 2008, 12:02 PM
It is NOT a periodic process. It is a demand based process when there is memory pressure at the time of a NEW allocation.
If you dont do new allocations, GC will NEVER execute. If there is no memory pressure GC will NEVER execute.
In C#, garbage collection is handled by the common language runtime (CLR) with similar functionality to that of the JVM. The CLR garbage collector periodically checks the memory heap for any unreferenced objects, and releases the resources held by these objects.
dglienna
May 20th, 2008, 01:44 PM
per Microsoft...
The garbage collector keeps track of objects that have Finalize methods, using an internal structure called the finalization queue. Each time your application creates an object that has a Finalize method, the garbage collector places an entry in the finalization queue that points to that object. The finalization queue contains entries for all the objects in the managed heap that need to have their finalization code called before the garbage collector can reclaim their memory.
...Even though I am not using "using" and since the traffic is low, I do not meet with any issues...
Sounds to me like: ' hey boys I'm driving a car since years without using security belts also driving with high speed... Here me friends ... never have had an accident.'
Hmm. Is this really a good explanation why people shouldn't use security belts. ?;)
I think most people will disagree:D Me too.
All this mechanics like Dispose, Using, finally ... are done for having well designed code, which doesn't lead to troubles by the leak of simple basics.
Download the Runtime (or use reflector), and LOOK. The ONLY place where it is checked is inside the allocation routine.
Arjay
May 21st, 2008, 01:48 AM
Thanks eclipsed4utoo,
1.
I think in your situation of "too many users are connected" is not because your code has bug which does not free handle, but because of GC does not free handles immediately?
2.
I think using Dispose call explicitly will solve this issue. :-)
regards,
GeorgeGeorge, what do you see as the downside of using a using block?
George2
May 21st, 2008, 05:09 AM
Thanks TheCPUWizard and eclipsed4utoo!
TheCPUWizard's comment for post #13 and eclipsed4utoo's post #14 seems both have formal resources or documents to support, but seems quite conflicting. Does anyone have any ideas what is the actual behavior? :-)
The downside is, I have to use Reflector to see what code is generated in order to understand the behavior. :-)
Just imagine the next version of C# compiler, the expanded code will change.
My current concern is, will expanded code catch all exceptions, or catch just Stream related exceptions or catch no exceptions and rethrow?
2.
If the exception is not re-throw, I have no chance to record a log for further problem determination. Any comments?
George, what do you see as the downside of using a using block?
regards,
George
George2
May 21st, 2008, 05:19 AM
Thanks JonnyPoet,
I do not use some technologies because I have no knowledge about them, not because them are bad -- to be honest. :wave: ;)
BTW: I have written down my concerns about using block in my post #21. Any ideas?
Sounds to me like: ' hey boys I'm driving a car since years without using security belts also driving with high speed... Here me friends ... never have had an accident.'
Hmm. Is this really a good explanation why people shouldn't use security belts. ?;)
I think most people will disagree:D Me too.
All this mechanics like Dispose, Using, finally ... are done for having well designed code, which doesn't lead to troubles by the leak of simple basics.
regards,
George
George2
May 21st, 2008, 05:21 AM
Hi TheCPUWizard,
Can you let us know which function/class are you talking about please? I am interested to learn further from you. I think you want to prove GC is only worked when memory is not enough, not working regulaly.
Download the Runtime (or use reflector), and LOOK. The ONLY place where it is checked is inside the allocation routine.
regards,
George
JonnyPoet
May 21st, 2008, 06:48 AM
My current concern is, will expanded code catch all exceptions, or catch just Stream related exceptions or catch no exceptions and rethrow?
but this has basically nthing to do with the usage of 'Using' or 'finally'
Both are to handle that your objects, streams, whatever are closed / disposed in a corrrect way when you dont need them anymore or when an exception is thrown. The exceptions aren't touched by them. The handling of exceptions is done in exactly that way your code will provide. Neither finally or Using throws any exceptions itself. This are two totally different shoes.
- You can see all exceptions are eaten. From outside you can not catch any more exceptions -- e.g. write a log or something. The exception is not rethrown. :-)
- In finally block, no exception handled for Dispose/Close method.
Any comments?
but this has basically nthing to do with the usage of 'Using' or 'finally'
Both are to handle that your objects, streams, whatever are closed / disposed in a corrrect way when you dont need them anymore or when an exception is thrown. The exceptions aren't touched by them. The handling of exceptions is done in exactly that way your code will provide. Neither finally or Using throws any exceptions itself. This are two totally different shoes.
try
{
using( Some IDisposable derived class )
{
// force or throw an exception here
}
}
catch( Exception e )
{
// see if this gets called
}
TheCPUWizard
May 21st, 2008, 11:34 AM
My current concern is, will expanded code catch all exceptions, or catch just Stream related exceptions or catch no exceptions and rethrow?
You ONLY catch those exceptions that meet the following requirements
1) You know the basic cause of the exception, and are confident that the application environment is in a predictable state
2) You can take some type of "correct action".
If EITHER of these do not apply, then the proper thing to do is to simply let the exception propogate.
ps: Browse through mscorlib.dll as well as System.dll for the basic internals...
George2
May 25th, 2008, 04:18 AM
Thanks Arjay,
1.
I have made some test program and you are correct. I have posted my code below, and can you have a quick review about whether my test approach is correct please?
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 ");
}
}
public static void Main()
{
try
{
using (MyObject myobj = new MyObject())
{
throw new MyException("Hello World");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
2.
I do not agree with you that Close method will be invoked, e.g. in your code "srObject.close()" -- I think only Dispose method is called. Any comments?
try
{
using( Some IDisposable derived class )
{
// force or throw an exception here
}
}
catch( Exception e )
{
// see if this gets called
}
regards,
George
George2
May 25th, 2008, 04:34 AM
Thanks TheCPUWizard,
One inferior point of using block is it does not catch exception occured in Dispose method. :-)
Any comments?
You ONLY catch those exceptions that meet the following requirements
1) You know the basic cause of the exception, and are confident that the application environment is in a predictable state
2) You can take some type of "correct action".
If EITHER of these do not apply, then the proper thing to do is to simply let the exception propogate.
ps: Browse through mscorlib.dll as well as System.dll for the basic internals...
regards,
George
Arjay
May 25th, 2008, 11:38 AM
I do not agree with you that Close method will be invoked, e.g. in your code "srObject.close()" -- I think only Dispose method is called.Of course this depends on how the developer has implemented it. A developer would have to be a bit brain dead not to release resources (i.e. internally call Close()) before disposing themselves since it's the point of Dispose.
Fortunately, the .net class libraries I use seem to do this. SqlConnection, SqlCommand, File I/O (readers, writers), Message Queue all seem to do it.
It's just good practice.
TheCPUWizard
May 25th, 2008, 11:59 AM
Of course this depends on how the developer has implemented it. A developer would have to be a bit brain dead not to release resources (i.e. internally call Close()) before disposing themselves since it's the point of Dispose..
Close but not exactly...
The "standard" is that Dispose() should do the WORK, and it is proper to create meaningful ALIAS's for Dispose that make bettersymantic sense.
Thus, (providing an instance does NOT support "re-opening", then Close() should in fact call Dispose(), and NOT the other way around.
- You can see all exceptions are eaten. From outside you can not catch any more exceptions -- e.g. write a log or something. The exception is not rethrown. :-)
- In finally block, no exception handled for Dispose/Close method.
No George. Sure the exceptions are NOT eaten. You need to handle them yourself. I'm using 'using' very often and use the upcoming exceptions for example for testing if the user has connecteto the correct database or if his password was wrong and all that. Per sure I have tested the code if it fires when pwd is wrong and all that. It works. So your idea is wrong in this way.
Arjay
May 25th, 2008, 02:09 PM
Close but not exactly...
The "standard" is that Dispose() should do the WORK, and it is proper to create meaningful ALIAS's for Dispose that make bettersymantic sense.
Thus, (providing an instance does NOT support "re-opening", then Close() should in fact call Dispose(), and NOT the other way around.This may be one case, but I don't believe it's the norm (at least with the IDisposable implementations that I'm familiar with).
For example, using reflector, here's the Dispose code for SqlConnection.
On the other hand, using reflector again, the Close() method doesn't call Dispose() (and as well it shouldn't).
The assembly I checked was System.Data.dll, version 2.0.0.0
I don't know if earlier versions did something different (if I recall, ver 1.0 didn't implement IDisposable). I suspect the later versions follow the same pattern as 2.0.
George2
May 26th, 2008, 03:49 AM
Thanks Arjay,
I agree with your points about Close/Dispose. What I mean is, using block is not smart enough to call Close other than call Dispose. It will always call Dispose. :-)
Of course this depends on how the developer has implemented it. A developer would have to be a bit brain dead not to release resources (i.e. internally call Close()) before disposing themselves since it's the point of Dispose.
Fortunately, the .net class libraries I use seem to do this. SqlConnection, SqlCommand, File I/O (readers, writers), Message Queue all seem to do it.
It's just good practice.
regards,
George
George2
May 26th, 2008, 03:51 AM
Thanks TheCPUWizard,
In my experience to learn code from books and MSDN, Close is just an alias for Dispose, and the function is always the same. Usually, Close just have one line of code, which calls Dispose.
Anyway, could you show us a case when the function of Close and Dispose are different please? :-)
Close but not exactly...
The "standard" is that Dispose() should do the WORK, and it is proper to create meaningful ALIAS's for Dispose that make bettersymantic sense.
Thus, (providing an instance does NOT support "re-opening", then Close() should in fact call Dispose(), and NOT the other way around.
regards,
George
George2
May 26th, 2008, 03:55 AM
Thanks JonnyPoet,
I have tested that for point 1, I am wrong. :blush:
But for point 2, from testing I think I am correct. In finally block generated automatically by using block, no exception handled for Dispose/Close method -- so the original exception will be missing.
Here is my code to verify, you can see MyException("Hello World") is missing. :-)
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());
}
}
}
No George. Sure the exceptions are NOT eaten. You need to handle them yourself. I'm using 'using' very often and use the upcoming exceptions for example for testing if the user has connecteto the correct database or if his password was wrong and all that. Per sure I have tested the code if it fires when pwd is wrong and all that. It works. So your idea is wrong in this way.
regards,
George
George2
May 26th, 2008, 04:07 AM
Hi Arjay,
On the other hand, using reflector again, the Close() method doesn't call Dispose() (and as well it shouldn't).
I am also using reflector to see .Net 2.0 code for SQL.Data.SqlClient.SqlConnection. I found in the finally block, Dispose is called. Here is my code from reflector. Any comments?
Look carefully at what is being disposed here. It's not the SqlConnection object, it's a member field _sdc of type SqlDebugContext.
George2
May 26th, 2008, 09:12 PM
Thanks Arjay,
You are correct. But what about the issue of original exception information missing when there is exception in Dispose method?
You can see in my below code. MyException("Hello World") is missing when there is exception in Dispose method.
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());
}
}
}
Look carefully at what is being disposed here. It's not the SqlConnection object, it's a member field _sdc of type SqlDebugContext.
regards,
George
TheCPUWizard
May 26th, 2008, 09:30 PM
On the other hand, using reflector again, the Close() method doesn't call Dispose() (and as well it shouldn't).
You didn't read a critical part of my post...
Thus, (providing an instance does NOT support "re-opening", then Close() should in fact call Dispose(), and NOT the other way around.
A SqlConnection can be Opened and Closed multiple times.
Look at other classes which do NOT allow "opening" after a call to close...
The Close method is a synonym for Dispose (which Message also implements). The message also disposes the object that was used to construct the body when it is disposed.
Cpu, I did read that part - that's why I responded with "it's not the norm".
The example that you cited Message.Close( ) as part of the preliminary documentation for the Silverlight class library also implements IDisposable.
As such, I would create it within a using block and call it a day.
using( Message msg = Message.CreateMessage( ... ) )
{
// do something with the message
}
In my opinion, explicitly calling Close() just clutters up the code.
TheCPUWizard
May 27th, 2008, 07:07 AM
using( Message msg = Message.CreateMessage( ... ) )
{
// do something with the message
}
In my opinion, explicitly calling Close() just clutters up the code.
100% agreement. But this is ONLY (IMHO) because of the using statement....
Remember there are ALOT of CLR based languages (my list is over 130 compilers). Many of these do not even expose the concept of exceptions to the developer. So the usage of an "alias" suuch as Close() may make sense in those circumstances.
For C#, the "rule" (enforced by my firm), is that the allocation must be done inside a using statement, or there must be specific (and docummented) reason why that pattern should not be followed. There should not be any explicit calls to Dispose() (or any alias's of Dispose()).
Arjay
May 27th, 2008, 08:51 AM
100% agreement. But this is ONLY (IMHO) because of the using statement....
Remember there are ALOT of CLR based languages (my list is over 130 compilers). Many of these do not even expose the concept of exceptions to the developer. So the usage of an "alias" suuch as Close() may make sense in those circumstances.
For C#, the "rule" (enforced by my firm), is that the allocation must be done inside a using statement, or there must be specific (and docummented) reason why that pattern should not be followed. There should not be any explicit calls to Dispose() (or any alias's of Dispose()).Sounds good to me. :thumb:
JonnyPoet
May 27th, 2008, 02:21 PM
try{
using (MyObject myobj = new MyObject()){
throw new MyException("Hello World");
}
}
catch (Exception ex){
Console.WriteLine(ex.ToString());
}
...
George this is totaly clear in my eyes as your Hallo World exception is eaten up by your exception you have thrown in the Dispose method. I did something like the following:
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace WindowsApplication1 {
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
try {
using (MyObject myobj = new MyObject()) {
string name = myobj.ToString();
throw new Exception("Hello World");
}
} catch (Exception ex) {
Console.WriteLine(ex.ToString());
}
}
}
public class MyObject:IDisposable {
public override string ToString() {
return "Hallo this is named 'MyObject'";
}
#region IDisposable Member
public void Dispose() {
Console.WriteLine("MyObject said: I'm Disposed");
// throw Exeption("Dispose Exception");
}
#endregion
}
}
Thus you will see the exception will be thrown. But when you additional throw an exception in the dispose method then your first ("HalloWorld") Exception isn't shown. My question is when there will happen an exception in the dispose method ? In my eyes errors during Disposing an object should never occure or should be handled within the Dispose method and then you have
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Xml;
namespace ConsoleApplication2 {
class Program {
static void Main(string[] args) {
try
{
using (MyObject myobj = new MyObject())
{
Console.WriteLine(myobj.ToString());
throw new MyException("inner exception");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
class MyException : ApplicationException {
public MyException (string message) : base(message){
}
}
class MyObject : IDisposable {
public virtual void Dispose()
{
try {
Console.WriteLine("Disposed ");
throw new MyException("Disposed exception. ");
} catch {
Console.WriteLine("Disposed Error Handled");
}
}
public override string ToString() {
return "This is MyObject";
}
}
}
}
And this will show you each exception. Add more Practice, not theory George ! :D ;)
George2
May 28th, 2008, 06:53 AM
Thanks TheCPUWizard!
1.
Remember there are ALOT of CLR based languages (my list is over 130 compilers). Many of these do not even expose the concept of exceptions to the developer. So the usage of an "alias" suuch as Close() may make sense in those circumstances.
Because of Close never throws any exception?
2.
For C#, the "rule" (enforced by my firm), is that the allocation must be done inside a using statement
I doubt this. I think we only need a reference type variable in the using statement. You can see similar to Arjay's Message creation sample, we can return an existing reference, no need to allocate (new) something. Any comments?
3.
There should not be any explicit calls to Dispose() (or any alias's of Dispose()).
Because of all Dispose is automatically generated by using block?
4.
You didn't read a critical part of my post...
A SqlConnection can be Opened and Closed multiple times.
Look at other classes which do NOT allow "opening" after a call to close...
I think the difference between Dispose and Close is, when we call Close, it is possible to call Open to re-open. but when we call Dispose, we can not re-open it, right?
regards,
George
George2
May 28th, 2008, 06:57 AM
Thanks Arjay,
It is good to learn from you below that we only need to return a reference variable, no need to explicitly allocate new instance in using statement, right?
Cpu, I did read that part - that's why I responded with "it's not the norm".
The example that you cited Message.Close( ) as part of the preliminary documentation for the Silverlight class library also implements IDisposable.
As such, I would create it within a using block and call it a day.
using( Message msg = Message.CreateMessage( ... ) )
{
// do something with the message
}
In my opinion, explicitly calling Close() just clutters up the code.
regards,
George
George2
May 28th, 2008, 07:04 AM
Thanks JonnyPoet,
For your code sample, there is an issue that you modified the code of Dispose method which handles exception itself.
Suppose in many cases we use libraries which does not allow us to change the code.
I have made imprvement of your code to never depends on changing code of Dispose method, and catch the exception inside using block before the automatically generated finally block by using block.
Here is my code, any comments?
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Xml;
using System;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
using (MyObject myobj = new MyObject())
{
try
{
Console.WriteLine(myobj.ToString());
throw new MyException("inner exception");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
class MyException : ApplicationException
{
public MyException(string message)
: base(message)
{
}
}
class MyObject : IDisposable
{
public virtual void Dispose()
{
try
{
Console.WriteLine("Disposed ");
throw new MyException("Disposed exception. ");
}
catch
{
Console.WriteLine("Disposed Error Handled");
}
}
public override string ToString()
{
return "This is MyObject";
}
}
}
}
regards,
George
Arjay
May 28th, 2008, 08:22 AM
Thanks Arjay,
It is good to learn from you below that we only need to return a reference variable, no need to explicitly allocate new instance in using statement, right?
regards,
GeorgeIncorrect. What do you think Message.CreateMessage(...) is doing?
JonnyPoet
May 28th, 2008, 01:47 PM
It is good to learn from you below that we only need to return a reference variable, no need to explicitly allocate new instance in using statement, right?
And from where do you think will Createmessage take the reference From a reference pool ? :eek: from Heaven ? :sick:
Please George! ;) dont expand the thread with quetion without using a bit of own research...
George2
June 1st, 2008, 09:03 PM
Thanks Arjay and JonnyPoet,
To show my point, here is my code. My question is, it is not a must to using "new" to create instance in "using" block?
static void Main(string[] args)
{
StreamWriter sw = new StreamWriter ("a.txt");
using (sw)
{
sw.WriteLine("I am fine");
}
return;
}
And from where do you think will Createmessage take the reference From a reference pool ? :eek: from Heaven ? :sick:
Please George! ;) dont expand the thread with quetion without using a bit of own research...