Try Catch Finally , pointers and Vb.net 2005 compiler warnings

C

Cor Ligthert [MVP]

Jay,
What do you do?

Be aware that I never used the using statement. However in this cases with a
datareader it can be (the change is low, however it is outside the process)
that the reading stops because of an exterior reason.

Think that you are making a long printing list and before the reading of the
last row it stops reading because of an hardware failure in the server and
the program goes down. Would you not want to tell to the user that not
everything is printed, although he could have the idea it was?

Another reason is than, that he not has directly to start again to try,
however first contact the administrator of that server.

Cor
 
C

Cor Ligthert [MVP]

David,

You spare me a message, I completly agree with you.

To show my opinion in this.

The only value reason I see not to do that is like this (and that does not
give a warning).
\\\
dim i as integer
try
'whatever code that needs a try
For i = 0 to 100
if i = 10 then exit
Next
Catch
end try
if i <> 10 then messagebox.show("something real strange hapened)
////

And for the rest I see no reasons to declare a variable outside its block
without assigning the object/value to it.

:)

Cor
 
C

Cor Ligthert [MVP]

David,

On the other hand am I afraid that people are starting this kind of C#
practise standard.

dim myObjectT as myClassT = nothing

Just to avoid the warning.

This adds nothing, it only creates something more to suppress standard the
warning and has for the rest no sense at all. Than an option is better that
people don't want to see this kind of warnings.

Just my opinion.

Cor
 
H

Herfried K. Wagner [MVP]

David Browne said:
No. The above code is and always was bad practice. Declaring local
variables without assigning them immediately is rarely the right thing to
do. Here the code should be:

I have to disagree. Imagine we are not using a simple form but we are using
a database connection object. Creating the object could throw an exception.
In this case an additional 'Try...Catch' block + conditional execution of
the following code would be required, which increases complexity.
 
H

Herfried K. Wagner [MVP]

Cor Ligthert said:
On the other hand am I afraid that people are starting this kind of C#
practise standard.

dim myObjectT as myClassT = nothing

I fear this will occur in VB.NET! Some months ago I had a long and
controversial discussion in the German C# group, and I stated that I think
that this warning doesn't necessarily lead to better code. Well, you can
imagine what C# people replied ;-).
Just to avoid the warning.

Yep. That's why I think that it's very important that the compiler only
raises this warning in cases where it is 100 percent sure (decided at
compile time) that an exception will be thrown at runtime.
 
H

Herfried K. Wagner [MVP]

Cor Ligthert said:
Be aware that I never used the using statement. However in this cases with
a datareader it can be (the change is low, however it is outside the
process) that the reading stops because of an exterior reason.

Think that you are making a long printing list and before the reading of
the last row it stops reading because of an hardware failure in the server
and the program goes down. Would you not want to tell to the user that not
everything is printed, although he could have the idea it was?

Another reason is than, that he not has directly to start again to try,
however first contact the administrator of that server.

Well, imagine the data is a long list of customers in a company and the
reader fails at customer 50,000 out of 100,000. Would you display the
50,000 customers only? This could lead to serious problems, and it might be
better to simply make the user aware that an error occured and the
application is currently out of service.
 
C

Cor Ligthert [MVP]

Herfried,
Well, imagine the data is a long list of customers in a company and the
reader fails at customer 50,000 out of 100,000. Would you display the
50,000 customers only? This could lead to serious problems, and it might
be better to simply make the user aware that an error occured and the
application is currently out of service.

--

That was what I tried to explain to Jay. I see that I did not succeed.

:)))

Cor
 
D

David Browne

Herfried K. Wagner said:
I have to disagree. Imagine we are not using a simple form but we are
using a database connection object. Creating the object could throw an
exception. In this case an additional 'Try...Catch' block + conditional
execution of the following code would be required, which increases
complexity.

No. The catch block should rethrow the exception. That _is_ conditional
execution of the following code.

But if creating the object throws an exception you don't have to dispose it.
The object creation belongs in a higher scope than its use and Dispose. But
big picture is that the using block should be used at every assignment of a
local variable to a Disposable type.

David
 
H

Herfried K. Wagner [MVP]

David Browne said:
No. The catch block should rethrow the exception. That _is_ conditional
execution of the following code.

This strongly depends on the scenario.
But if creating the object throws an exception you don't have to dispose
it.

That's true. However, the construct I showed was not intended to be a
replacement for simple cases of 'Using' which are dealing with a single
object only. My main concern is about the uselessness of the compiler
warning.
The object creation belongs in a higher scope than its use and Dispose.

I believe it belongs to the same scope if possible. Higher scopes are
possible, but not always the best solution (minimum scope is often the best
choice, and in this particular case it's the same scope).

The main question is -- and this question has been discussed hundreds of
times -- whether or not the 'Try', 'Catch', and 'Finally' branches should
share the same scope.
But big picture is that the using block should be used at every
assignment of a local variable to a Disposable type.

The 'Using' block has IMO one big disadvantage: It introduces an additional
scope, although the 'Dispose' pattern has nothing to do with scopes.
 
J

Jay B. Harlow [MVP - Outlook]

David,
| Yes, I didn't want to change the posted code, point out that variables
| Disposables should be instantiated before the Try blocks in which they
| disposed, not inside them.
Sometimes, but not all the times!

Use ILDASM to look at the Using statement, the initialization code is inside
the Try block!

--
Hope this helps
Jay [MVP - Outlook]
..NET Application Architect, Enthusiast, & Evangelist
T.S. Bradley - http://www.tsbradley.net


message |
| message | > David,
| > Err, Oops...
| >
| > Try:
| >
| > | Dim f As new Form()
| > | Try
| > | 'use f
| >
| > Finally
| >
| > | f.Dispose()
| > | End Try
| >
| > As you want to Dispose of the variable even if (*especially if*) an
| > exception is NOT thrown!
| >
|
| Yes, I didn't want to change the posted code, point out that variables
| Disposables should be instantiated before the Try blocks in which they
| disposed, not inside them.
|
| David
|
|
 
J

Jay B. Harlow [MVP - Outlook]

Cor,
| the program goes down. Would you not want to tell to the user that not
| everything is printed, although he could have the idea it was?
Yes, my "global exception handlers" tell the user that not every thing
printed, as well as stop the printing itself.

As the Connection itself may have failed, the creation of the PrintDocument
may have failed, the creation of any number of System.Drawing objects may
have failed, any number of other things may have failed...

What I am saying is you don't need the *Catch* block by the read, you need
the *Finally* block by the read. As the *Finally* block is what cleans up
any resources that the read may have used.


--
Hope this helps
Jay [MVP - Outlook]
..NET Application Architect, Enthusiast, & Evangelist
T.S. Bradley - http://www.tsbradley.net


| Jay,
|
| > What do you do?
|
| Be aware that I never used the using statement. However in this cases with
a
| datareader it can be (the change is low, however it is outside the
process)
| that the reading stops because of an exterior reason.
|
| Think that you are making a long printing list and before the reading of
the
| last row it stops reading because of an hardware failure in the server and
| the program goes down. Would you not want to tell to the user that not
| everything is printed, although he could have the idea it was?
|
| Another reason is than, that he not has directly to start again to try,
| however first contact the administrator of that server.
|
| Cor
|
|
 
C

Cor Ligthert [MVP]

Jay,
| the program goes down. Would you not want to tell to the user that not
| everything is printed, although he could have the idea it was?
Yes, my "global exception handlers" tell the user that not every thing
printed, as well as stop the printing itself.
I expressly have written that if you do use "using" in the situation of the
datareader (with an external server) you *need* the global exception
handlers as you wrote at the end of your message. That was the reason of my
first reply to you beside the other reason I found it important extra to
point on that.

see bellow
In my opinion is that a must with a datareader where a connection can give
trouble.

I wrote as well that I did not like those global Try/Catch blocks and
therefore will not use the *using* in this kind of situations and therefore
need a Try Catch block.

I wrote as well that I could not give a good reasonable explanation why I do
not use them.

Probably I don't set it globally because that I find them to global from the
problem and don't give me that good feeling that every thing is catched.
Almost the same reason that I don't like to put more things globally.

Cor
 
M

Mattias Sjögren

Jay,
Use ILDASM to look at the Using statement, the initialization code is inside
the Try block!

Not on my machine (with beta 2). If that's really what you're seeing I
suggest you file a bug because it would violate the spec.


Mattias
 
J

Jay B. Harlow [MVP - Outlook]

Doh!
I really need to verify gradious statements. :-(

Below is from VB 2005 Beta 2 the initialize is outside the Try, however the
Finally still checks for Null/Nothing as the Try block could have set it to
nothing.

So now I'm left wondering where I saw it in IL that it was inside...


Private Sub About_Click(ByVal button As Office.CommandBarButton, ByRef
CancelDefault As Boolean)
Using dialog As New AboutBoxForm
dialog.ShowDialog()
End Using
End Sub


..method private instance void About_Click(class
[office]Microsoft.Office.Core.CommandBarButton button,
bool& CancelDefault) cil managed
{
// Code size 41 (0x29)
.maxstack 2
.locals init ([0] class XmlExportSample.AboutBoxForm dialog,
[1] bool VB$CG$t_bool$S0)
.language '{3A12D0B8-C26C-11D0-B442-00A0244A1DD2}',
'{994B45C4-E6E9-11D2-903F-00C04FA302A1}',
'{5A869D0B-6611-11D3-BD2A-0000F80849BD}'
// Source File 'C:\Documents and Settings\jay\My Documents\Visual Studio
2005\Projects\Xml Export Sample\Xml Export Sample\UIController.vb'
//000115: Private Sub About_Click(ByVal button As
Office.CommandBarButton, ByRef CancelDefault As Boolean)
IL_0000: nop
//000116: Using dialog As New AboutBoxForm
IL_0001: nop
IL_0002: newobj instance void XmlExportSample.AboutBoxForm::.ctor()
IL_0007: stloc.0
IL_0008: nop
//000117: dialog.ShowDialog()
.try
{
IL_0009: ldloc.0
IL_000a: callvirt instance valuetype
[System.Windows.Forms]System.Windows.Forms.DialogResult
[System.Windows.Forms]System.Windows.Forms.Form::ShowDialog()
IL_000f: pop
//000118: End Using
IL_0010: nop
IL_0011: leave.s IL_0027
} // end .try
finally
{
IL_0013: ldloc.0
IL_0014: ldnull
IL_0015: ceq
IL_0017: ldc.i4.0
IL_0018: ceq
IL_001a: stloc.1
IL_001b: ldloc.1
IL_001c: brfalse.s IL_0025
IL_001e: ldloc.0
IL_001f: callvirt instance void
[mscorlib]System.IDisposable::Dispose()
IL_0024: nop
IL_0025: nop
IL_0026: endfinally
//000119: End Sub
} // end handler
IL_0027: nop
IL_0028: ret
} // end of method UIController::About_Click



--
Hope this helps
Jay [MVP - Outlook]
..NET Application Architect, Enthusiast, & Evangelist
T.S. Bradley - http://www.tsbradley.net


message | David,
|| Yes, I didn't want to change the posted code, point out that variables
|| Disposables should be instantiated before the Try blocks in which they
|| disposed, not inside them.
| Sometimes, but not all the times!
|
| Use ILDASM to look at the Using statement, the initialization code is
inside
| the Try block!
|
| --
| Hope this helps
| Jay [MVP - Outlook]
| .NET Application Architect, Enthusiast, & Evangelist
| T.S. Bradley - http://www.tsbradley.net
|
|
| message ||
|| message || > David,
|| > Err, Oops...
|| >
|| > Try:
|| >
|| > | Dim f As new Form()
|| > | Try
|| > | 'use f
|| >
|| > Finally
|| >
|| > | f.Dispose()
|| > | End Try
|| >
|| > As you want to Dispose of the variable even if (*especially if*) an
|| > exception is NOT thrown!
|| >
||
|| Yes, I didn't want to change the posted code, point out that variables
|| Disposables should be instantiated before the Try blocks in which they
|| disposed, not inside them.
||
|| David
||
||
|
|
 
J

Jay B. Harlow [MVP - Outlook]

Mattias,
As I just posted: I verified after the fact and you are correct its not in
Beta 2.

I remember seeing the initialize inside someplace, but now I really don't
remember where.

--
Hope this helps
Jay [MVP - Outlook]
..NET Application Architect, Enthusiast, & Evangelist
T.S. Bradley - http://www.tsbradley.net


| Jay,
|
| >Use ILDASM to look at the Using statement, the initialization code is
inside
| >the Try block!
|
| Not on my machine (with beta 2). If that's really what you're seeing I
| suggest you file a bug because it would violate the spec.
|
|
| Mattias
|
| --
| Mattias Sjögren [MVP] mattias @ mvps.org
| http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
| Please reply only to the newsgroup.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top