ALways Initializing Objects

  • Thread starter Thread starter JSheble
  • Start date Start date
J

JSheble

I'm writing some code that interacts with MSMQ, and am getting in the habit
of using try{}catch{}finally{} blocks, but am now running into a problem
with un-initialized variables... for example, consider the following method:

private void GetQMessage()
{
System.Messaging.Message oMsg;
System.Messaging.MessageQueue oMsgQ = new MessageQueue(this.StatusQ);
oMsgQ.Formatter = new XmlMessageFormatter(new Type[] {typeof(String)});

try
{
oMsg = oMsgQ.Receive(new TimeSpan(0, 0, 0, 15, 0));

if(((String) oMsg.Body) != "")
{
this.lstActivity.Items.Insert(0, (String) oMsg.Body);
}
else
{
this.lstActivity.Items.Insert(0, "QWatcher Appears To Be Idle");
}
}
catch(MessageQueueException err)
{
if(err.MessageQueueErrorCode == MessageQueueErrorCode.IOTimeout)
{
this.lstActivity.Items.Insert(0, "QWatcher Appears To Be Idle");
}
}
finally
{
if(this.lstActivity.Items.Count > 250)
{
this.lstActivity.Items.RemoveAt(250);
}

oMsg.Dispose();
oMsgQ.Dispose();
}
}

When I compile this, I get the following error: FormMain.cs(129): Use of
unassigned local variable 'oMsg', which points to the oMsg.Dispose() call in
the finally block.

Now I like the fact that each block of code can have it's own variable
scope, but when using exception handling, it's a bit inconvienent. SO
what's the best way of handling this?? SHould I always initialize the
actual object to an empty object? (i.e. Message oMsg = new Message();)
 
JSheble said:
I'm writing some code that interacts with MSMQ, and am getting in the habit
of using try{}catch{}finally{} blocks, but am now running into a problem
with un-initialized variables... for example, consider the following method:

In the case of disposing of objects, the solution is almost always to
use a "using" block which will automatically call Dispose for you. In
your particular case, you'll still need a finally block for the
trimming, but you won't need to call Dispose manually.
 
Originally, I wasn't even calling the Dispose() method at all, but came
across an article online that said it's a good practice to get into, so I
added them. This particular example used dispose, but here's another more
legitimate example, where I get the same error about using an uninitialized
variable. In this example, I always want the recordset (OleDbDataReader) to
always close, but the oRecs variable doesn't get intialized until the try{}
block. So how would I ensure the oRecs recordset is indeed closed?

Also, what exactly do you mean by using a "using" block??

private decimal AddAddress(OleDbCommand oleCmd, AddressType tType,
GlobalShip.GSAddress oAddress)
{
string sAddressType = "";
decimal iAddressID = 0;
string sQuery = "";
OleDbDataReader oRecs;

switch(tType)
{
case AddressType.Destination:
sAddressType = "DESTINATION_ADD";
break;

case AddressType.Origin:
sAddressType = "ORIGIN";
break;

case AddressType.Payee:
sAddressType = "PAYEE";
break;

case AddressType.Return:
sAddressType = "RETURN";
break;
}

sQuery = "INSERT INTO LIVE.ADDRESSES(" +
"CATEGORY, " +
"COMPANY, " +
"ADDRESS_LINE_1, " +
"ADDRESS_LINE_2, " +
"CITY, " +
"STATE, " +
"ZIP, " +
"PHONE, " +
"COUNTRY_CODE) " +
"VALUES(" +
"'" + sAddressType + "', " +
"'" + oAddress.CompanyName + "', " +
"'" + oAddress.Address1 + "', " +
"'" + oAddress.Address2 + "', " +
"'" + oAddress.City + "', " +
"'" + oAddress.State + "', " +
"'" + oAddress.ZipCode + "', " +
"'" + oAddress.Phone + "', " +
"'" + oAddress.Country + "')";

try
{
oleCmd.CommandText = sQuery;
oleCmd.ExecuteNonQuery();
oleCmd.CommandText = "VALUES(IDENTITY_VAL_LOCAL())";
oRecs = oleCmd.ExecuteReader();
oRecs.Read();
iAddressID = oRecs.GetDecimal(0);
}
catch(Exception err)
{
throw(new MyDataException("Unable to insert Address", err));
}
finally
{
oRecs.Close();
}

return(iAddressID);
}
 
JSheble said:
Originally, I wasn't even calling the Dispose() method at all, but came
across an article online that said it's a good practice to get into, so I
added them. This particular example used dispose, but here's another more
legitimate example, where I get the same error about using an uninitialized
variable. In this example, I always want the recordset (OleDbDataReader) to
always close, but the oRecs variable doesn't get intialized until the try{}
block. So how would I ensure the oRecs recordset is indeed closed?

Also, what exactly do you mean by using a "using" block??

You'd do:

using (OleDbDataReader oRecs = oleCmd.ExecuteReader())
{
oRecs.Read();
iAddressID = oRecs.GetDecimal(0);
}

Note that this keeps the declaration of the variable at the point of
first use, which is another good habit to get into - I had to look
around for a while to find out what type oRecs was to start with.

(As a side note, you should be using query parameters rather than
putting values directly into the SQL, but that's a different issue.)
 
(As a side note, you should be using query parameters rather than
putting values directly into the SQL, but that's a different issue.)

Excuse my ignorance, but what would that accomplish? Advantages?
Disadvantages?
 
System.Messaging.Message oMsg;
Change to
System.Messaging.Message oMsg = null;
oMsg.Dispose();
oMsgQ.Dispose();

Change to

if (oMsg != null) oMsg.Dispose();
if (oMsgQ != null) oMsgQ.Dispose();

--
Jonathan Allen


JSheble said:
I'm writing some code that interacts with MSMQ, and am getting in the
habit of using try{}catch{}finally{} blocks, but am now running into a
problem with un-initialized variables... for example, consider the
following method:

private void GetQMessage()
{
System.Messaging.Message oMsg;
System.Messaging.MessageQueue oMsgQ = new MessageQueue(this.StatusQ);
oMsgQ.Formatter = new XmlMessageFormatter(new Type[] {typeof(String)});

try
{
oMsg = oMsgQ.Receive(new TimeSpan(0, 0, 0, 15, 0));

if(((String) oMsg.Body) != "")
{
this.lstActivity.Items.Insert(0, (String) oMsg.Body);
}
else
{
this.lstActivity.Items.Insert(0, "QWatcher Appears To Be Idle");
}
}
catch(MessageQueueException err)
{
if(err.MessageQueueErrorCode == MessageQueueErrorCode.IOTimeout)
{
this.lstActivity.Items.Insert(0, "QWatcher Appears To Be Idle");
}
}
finally
{
if(this.lstActivity.Items.Count > 250)
{
this.lstActivity.Items.RemoveAt(250);
}

oMsg.Dispose();
oMsgQ.Dispose();
}
}

When I compile this, I get the following error: FormMain.cs(129): Use of
unassigned local variable 'oMsg', which points to the oMsg.Dispose() call
in the finally block.

Now I like the fact that each block of code can have it's own variable
scope, but when using exception handling, it's a bit inconvienent. SO
what's the best way of handling this?? SHould I always initialize the
actual object to an empty object? (i.e. Message oMsg = new Message();)
 
JSheble said:
Excuse my ignorance, but what would that accomplish? Advantages?
Disadvantages?

The main advantage is to avoid SQL injection attacks - you don't need
to worry about whether the user input needs to be escaped or not, etc.
It can also have performance advantages on some databases.

There aren't any disadvantages that I know of.
 
Thanx... after doing a few Google searches, and reading some various
articles, I've changed my queries to parameterized queries...
 
One other thing, the performance benefits are sizeable on Oracle and
Microsoft SQL Server, among others.

Most DB's have a statement/execution-plan cache. Both Oracle and SQL (and
probably the others) treat Stored Procs and prepared statements the same,
esentially. In fact, prepared statements have some advantages over stored
procs for executing simple C/R/U/D queries. Use stored procs only if you
need to actually do some functionality server side (execute several
statements in the same transaction on on the server, etc).

-c

JSheble said:
Thanx... after doing a few Google searches, and reading some various
articles, I've changed my queries to parameterized queries...
 
Back
Top