As it is, I tried error-proofing my code and ended up making it look quite messy.
I have a function set up to read a certain type of file. I want the function to return false if there was a problem, or true if everything worked. I'm having trouble figuring out how to structure everything.
I have an initial try-catch block that tries to open a file stream. After that though, I have certain other checks I make during the reading process such as file size and values at certain offsets. The way I set it up was with if else statements. Such as:
if(condition){
}
else{
MessageBox.Show("There was an error");
br.Dispose();
fs.Dispose();
return false;
}
...br being the binary reader and fs the filestream. There are many blocks like this, and it seems like bad practice to write the same thing so many times. The first thing that comes to mind is to wrap the entire thing in a try-catch statement and throw exceptions instead of using the if else blocks. I remember when reading about try-catch statements that it's good to have them, but not to wrap everything with them. To be honest, I still don't completely understand why it would be bad practice to wrap everything in try catch statements, as they only have an effect when there's an error, in which case the program is going south anyway...
Also, do I have to close the binary reader and file stream, or will closing one close the other? Is there any way to use them without having to dispose of them?
How about making use of the using keyword? this wraps your use of an IDisposable in a try - finally block;
bool success = true;
using(var fs = new FileStream(fileName, FileMode.Create)))
using(var br = new BinaryReader(fs))
{
// do something
success = result;
}
return success;
The nested using blocks will ensure that both the filestream and binary reader are always properly closed and disposed.
You can read more about using in MSDN. It makes the use of IDisposable a little neater, removing the need for explicit excpetion handling.
Regarding your statement:
I remember when reading about try-catch statements that it's good to
have them, but not to wrap everything with them.
I always use the simple rule that if I cannot handle and recover from an exception within a particular block of code, don't try to catch it. Allow the exception to 'bubble up' the stack to a point where it makes more sense to catch it. With this approach you will find that you do not need to add many try-catch blocks, you will tend to use them at the point of integration with services (such as filesystem, network etc ...) but your business logic is almost always free of exception handling mechanisms.
Just use the using keyword for your disposable objects. Within the block of the using keyword you can throw exceptions or return without having to worry about disposal; it will happen automagically for you.
try-catch blocks are not a very good idea only because there exists a much better alternative: the try-finally blocks. But the using keyword is even better because it essentially expands into a try-finally block and it takes care of object disposal.
Closing the file stream will also close the binary reader, and so will disposing of them do. Why do you want to use them without disposing them? Disposing them is better, and disposing them via using is the best thing to do.
I think the best way to make sure filestreams are disposed is to wrap their usage with the following using block
using (FileStream)
{
....
}
Yes, it is bad practice.
Instead of returning booleans that indicate whether a problem occurred or not, you should throw exceptions. Example:
if (headNotValid)
throw new Exception("Header was not valid");
In some cases it may be advisable to make a new exception class.
When working with classes that inherit from IDisposable you should use the using directive.
using (var stream = new FileStream(filename))
{
}
That guarantees, that your stream is disposed, even if a exception is thrown within the using block.
In summary, I would prefer something like this:
private void string ParseFile(string filename)
{
using (var stream = new FileStream(filename))
{
if (somethingNotValid)
throw new Exception(...);
return ...;
}
}
And in your main:
{
try
{
var value = ParseFile(filename);
}
catch (Exception)
{
Console.WriteLine(..);
}
}
Use the using keyword. With using you can rewrite something like this:
public static int CountCars()
{
SqlConnection conn = new SqlConnection(connectionString);
try
{
SqlCommand cmd = conn.CreateCommand();
conn.Open();
try
{
cmd.CommandText = "SELECT COUNT(1) FROM Carsd";
return (int)cmd.ExecuteScalar();
}
finally
{
if(cmd != null)
cmd.Dispose();
}
}
finally
{
if(cmd != null)
conn.Dispose();
}
}
into this:
public static int CountCars()
{
using(SqlConnection conn = new SqlConnection(connectionString))
using(SqlCommand cmd = conn.CreateCommand())
{
conn.Open();
cmd.CommandText = "SELECT COUNT(1) FROM Carsd";
return (int)cmd.ExecuteScalar();
}
}
Both code snippets will produce exactly the same IL code when compiled. The examples are from http://coding.abel.nu/2011/12/idisposable-and-using-in-c/ where I wrote some more details about using and IDisposable.
Related
I have a method that returns a List. Now I want to know how to place the try/catch blocks properly. If I place the return statement inside try I get error
Not all code paths return a value
If I place after catch(like I'm doing currently) it will return the products even after an Exception. So what should be the best way?
Here is the method:
public List<Product> GetProductDetails(int productKey)
{
List<Product> products = new List<Product>();
try
{
using (SqlConnection con = new SqlConnection(_connectionString))
{
SqlCommand cmd = new SqlCommand("usp_Get_ProductDescription", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#riProductID", productKey);
con.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
Product product = new Product(reader["Name"].ToString(), reader["Code"].ToString());
products.Add(product);
}
}
}
}
catch { }
return products;
}
Remove the complete Try and Catch blocks. Apparently you are unable to handle the exceptions in the GetProductDetails method so just let them be thrown.
However the calling code can make the decision:
IList<Product> products = null;
try
{
products = GetProductDetails(3);
}
catch(Exception ex)
{
// Here you can make the decision whether you accept an empty list in case of retrieval errors.
// It is the concern of this method, not of the ProductDetails method.
// TODO: Use logging
products = new List<Product>();
}
I can imagine it feels like code duplication if you have to write this in every method using the GetProductDetails method. However consider, when you have X implementations, you want to react differently to not being able to get product details. You will have to come up with workarounds. You might even end up with weird bugs which are hard to troubleshoot.
That depends on what should happen in an exceptional case. If this might happen for some reason which isnĀ“t "bad enough" to let the app crash or if you are able to handle that exception appropriately then you might go with your current appraoch - however you should definitly leave at least a log-message within the catch-clause that contains the error which has been thrown:
catch (Exception e)
{
log.Info(e.Message);
}
This way you get all results within your list except those that caused any exceptions. You can simply continue work with all the results that you got and ignore those errorous (supposing you logged them in any way).
If it is a really unexpected behaviour (which is the intended one for exceptions, this is why they are called exceptions) you should delete all this try/catch from within your method and handle any exceptions outside the method as Maurice already mentioned.
At the moment, you don't return anything if an exception is thrown.
Use try, catch, finally. (May you want to see the MSDN page for more official information)
try
{
//try to execute this code
}
catch
{
//execute this if an exception is thrown
}
finally
{
//execute this code, after try/catch
}
So if you place your return statement into the finally section, you will return your list even if there's an exception thrown...
I wonder if the object created in the usingstatement gets disposed if I perform a return or throw operation. Example as follows.
using(SomeClass thing = new SomeClass())
{
...
if(condition)
return;
...
}
Will the above get confused or is GC to be trusted here?
Yes, it will. The using statement will result in a finally block being created. A finally block's code will be run even if an exception is thrown in the related try block, or if there is a return statement in that try block.
There are only a few exceptions that can cause a finally block's code to not be executed, and they are all listed here, but my guess is that in your situation you'll be able to live with those consequences.
using is the equivalent of try-finally so, yes, it does.
dispose if it is implemented will always get called. Its the equivalent of calling dispose in a finally block.
It will dispose, yes. It will create a finally block in the CIL code.
Yes, because using is extended into a try finally by the compiler. The dispose will occur inside the finally block. Also, the finally will contain a test to check if the variables in the using are null (in case there are exceptions on the constructors).
When writing a using statement:
using(SomeClass thing = new SomeClass())
{
//...
if (condition)
return;
//...
}
this will result in the following code:
SomeClass thing;
try
{
thing = new SomeClass();
//...
if (condition)
return;
//...
}
finally
{
if(thing != null)
{
thing.Dispose();
}
}
So all object declared using ( /* HERE */ ) will get disposed automatically. Objects declared inside the {} won't.
But you can of course nest (or stack) using statements:
using (var thing = new SomeClass())
using (var another = new Another())
using (var somethingElse = new Whatever())
{
//...
}
which in turn of course is just the syntactic sugar for writing
using (var thing = new SomeClass())
{
using (var another = new Another())
{
using (var somethingElse = new Whatever())
{
//...
}
}
}
because when a statement is followed by just one block of code (in this case another using-block) you can skip the curly braces...
When using two or more objects of the same type you can chain the declaratio within the using-statement:
using (MemoryStream stream = new MemoryStream(), stream2 = new MemoryStream())
{
//...
}
(Thanks to #Gratzy for pointing that out)
For me, the question does not match with the details, and the details have been addressed here a bunch but not the title question...
Does using dispose all the the objects declared in it?
NO, it does not. It only calls Dispose() for the object(s) in its declaration. It does not call Dispose() for objects declared in it.
I usually see this kind of thing in code
using(var sqlConn = new SqlConnection("connStr"))
using(var sqlCmd = new SqlCmd("CmdText", sqlConn))
{
sqlConn.Open();
var reader = sqlCmd.ExecuteReader();
while (reader.Read())
{
//stuff is done
}
}
This will dispose and close both sqlConn and sqlCmd when the scope is complete for those but the reader that was declared in the using scope does not have Dispose() automatically called for it .
I found that my codebase contains various data access code where I have used using statements in two different ways. Which is the better way if any and are these two methods different? Any problems that could arise from not instantiating the SqlConnection and SqlCommand in the using statement? Ignore the obvious inconsistency problem.
Method 1:
public int SampleScalar(string query, CommandType queryType, SqlParameter[] parameters)
{
int returnValue = 0;
SqlConnection objConn = new SqlConnection(ConnString);
SqlCommand objCmd = new SqlCommand(query, objConn);
objCmd.CommandType = queryType;
if (parameters.Length > 0)
objCmd.Parameters.AddRange(parameters);
using (objConn)
{
using (objCmd)
{
objConn.Open();
try
{
returnValue = (int)objCmd.ExecuteScalar();
}
catch (SqlException e)
{
Errors.handleSqlException(e, objCmd);
throw;
}
}
}
return returnValue;
}
Method 2:
public int SampleScalar2(string query, CommandType queryType, SqlParameter[] parameters)
{
int returnValue = 0;
using (SqlConnection objConn = new SqlConnection(ConnString))
{
using (SqlCommand objCmd = new SqlCommand(query, objConn))
{
objConn.Open();
objCmd.CommandType = queryType;
if (parameters.Length > 0)
objCmd.Parameters.AddRange(parameters);
try
{
returnValue = (int)objCmd.ExecuteScalar();
}
catch (SqlException e)
{
Errors.handleSqlException(e, objCmd);
throw;
}
}
}
return returnValue;
}
In the first snippet, if there are any exceptions that occur after the IDisposable object is created and before the start of the using, then it won't be properly disposed. With the second implementation, there is no such gap that could result in unreleased resources.
Another problem that can occur with the first approach is that you could use an object after it has been disposed, which is not likely to end well.
It's possible that you are ensuring no exception could possibly occur, and maybe you're not. In general, I would never use the first method simply because I don't trust myself (or anyone else) to never ever ever make a mistake in that unprotected space. If nothing else, I'll need to spend time and effort looking very closely to be sure that nothing can ever go wrong. You don't really gain anything from using that less-safe method either.
I always go with the second method. It's easier to read and understand what objects are being disposed of at the end of a given block. It will also prevent you from using an object that has been disposed.
If you not use using you don't dispose your objets no managed, and GC no dispose
GC dispose only objects managed and sql connection is not managed so you must dispose, using use dispose in the end
Second one is better. Please read http://msdn.microsoft.com/en-us/library/yh598w02.aspx last remark.
In first object stays in scope after it's disposal. Using it then is not good practice.
Per MSDN
You can instantiate the resource object and then pass the variable to the using statement, but this is not a best practice. In this case, the object remains in scope after control leaves the using block even though it will probably no longer have access to its unmanaged resources. In other words, it will no longer be fully initialized. If you try to use the object outside the using block, you risk causing an exception to be thrown. For this reason, it is generally better to instantiate the object in the using statement and limit its scope to the using block.
Ive been doing some research today on when an how to use the "using" statement to dispose of my sql objects.
However I'm still confused about when and how to catch unforseen errors. I have a simple method here and would appreciate any input on wheter its correct or I'm doing something wrong?
private BindingList<My_Object> Search(int ID)
{
string strSelectStatement =
"SELECT 'coloumns' " +
"FROM 'table' " +
"WHERE ID = #ID;";
DataTable dt = new DataTable();
try
{
using (SqlConnection sqlConn = new SqlConnection(m_SQLConnectionString))
{
using (SqlCommand cmd = new SqlCommand(strSelectStatement, sqlConn))
{
cmd.Parameters.Add("#ID", SqlDbType.Int).Value = ID;
using (SqlDataAdapter adpt = new SqlDataAdapter(cmd))
{
adpt.Fill(dt);
}
}
}
My_Object myObject;
BindingList<My_Object> myObjectList = new BindingList<My_Object>();
foreach (DataRow row in dt.Rows)
{
myObject = new My_Object();
//Fill/set myObject properties and add to myObject list
}
return myObjectList;
}
catch (Exception)
{
//throw the the exception with its stack trace up to the main call
throw;
}
}
So what my catch here would do is catch an error if anything went wrong when running adapter.Fill, or while building myObject/list for example.
Thanks
In C# . The using statement defines the scope of an item to be disposed. This can be called for any object which implements the IDisposable interface.
http://msdn.microsoft.com/en-us/library/system.idisposable.aspx
So if you had to not use using blocks you would call the dispose method on the class to release/clean up resources created by the object.
When calling a class that implements the IDisposable interface, the try/finally pattern make sure that unmanaged resources are disposed of even if an exception interrupts your application.
If an exception is thrown in the case of a using statement the dispose will still be called. You can also stack using statements
using (SqlConnection sqlConn = new SqlConnection(m_SQLConnectionString))
using (SqlCommand cmd = new SqlCommand(strSelectStatement, sqlConn))
{
cmd.Parameters.Add("#ID", SqlDbType.Int).Value = ID;
using (SqlDataAdapter adpt = new SqlDataAdapter(cmd))
{
adpt.Fill(dt);
}
}
with regards to exception handling. It is not wise to catch all exceptions try to catch the specific exceptions thrown by the class or method. You can view exception details on msdn so SQLConnection : http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.open.aspx
InvalidOperationException
Cannot open a connection without specifying a data source or server.
or
The connection is already open.
SqlException
A connection-level error occurred while opening the connection. If the Number property contains the value 18487 or 18488, this indicates that the specified password has expired or must be reset. See the ChangePassword method for more information.
So these are the exceptions you should cater for. Hope that helps!
Don't catch 'unforeseen' errors, since there's nothing you can do if truly unforeseen.
Unless of course you are wishing to handle these errors in some way, say, to log messages - but the system does that for you - then they are no longer 'unforeseen', since you're expecting them.
As for the code posted, there are problems. Firstly, the try / catch could be said to be trying too much, and given that you have usings in there, that is pointless (if exceptions aren't going to be handled.) It also catches a generic exception, which is highly discouraged; catches should be formulated to filter those that you can handle, and in appropriate order. To catch just to throw is also pointless.
Don't catch exceptions if you can do nothing about it. If you catch them is in order to clean up the unmanaged ressources or for logging purposes.
You might have a look on MSDN "Best Practices for Handling Exceptions" http://msdn.microsoft.com/en-us/library/seyhszts.aspx
You don't need the try..catch {throw}. This is the same as not having a try..catch block at all.
If you want to log the error of display a friendly message, then put the code in the catch { }.
The Dispose will still be called on the SqlConnection, even if the code crashes.
You can catch multiple exceptions at the end of your try statement. This means you can catch each different type of error that could occur i.e. InvalidOperationException / SqlException. MSDN Explains here:
http://msdn.microsoft.com/en-us/library/ms173162(v=vs.80).aspx
Since you have enclosed your whole code in try/Catch it will catch all errors raised within try/catch code block.
But don't follow this apprach only catch those errors specifically which you want to handle or log.
this is recommended because catching error is an overhead.
I am trying to come up myself with an acceptable pattern for data reading from DB using Enterprise Library. How do you consider the following pattern (I mean, the null-check in the finally block)?
IDataReader NewReader = null;
try
{
NewReader = (SqlDataReader)(SqlDatabase.ExecuteReader(SqlCommand));
/* Do some work with NewReader. */
NewReader.Close();
}
catch /* As much 'catch' blocks as necessary */
{
/* Handle exceptions */
}
finally
{
if (!ReferenceEquals(NewReader, null))
{
NewReader.Dispose();
}
}
Is this null-check acceptable, or is there a more elegant way of solving this problem?
I would use if(NewReader == null). It's the default way of checking for null. Your way of doing it is the same, but it looks strange and thus might confuse people.
Besides: Why don't you use using? Makes your code a lot cleaner:
try
{
using(IDataReader NewReader = (SqlDataReader)(SqlDatabase.ExecuteReader(SqlCommand)))
{
/* Do some work with NewReader. */
}
}
catch /* As much 'catch' blocks as necessary */
{
/* Handle exceptions */
}
It is the same as:
if (NewReader != null) ...
which I would prefer from a styling point of view.
Update:
As NewReader seemingly implements IDisposable, just wrap it in a using construct.
Example:
using (var r = new ReaderSomething())
{
try
{
}
catch {}
}
I would prefer using the "using" block as:
using(<your reader object>)
{
//read data from reader
}
Just to add a bit of detail to what people have said above...
Use a using block as, regardless of whether an exception occurs or not, the Dispose method will automatically be called due to implementations of IDataReader having to also implementing IDisposable.