Getting a try catch to continue 'trying' and 1st exception - c#

I wonder if someone could give me some advice please?
I need to check for the existence of some session variables in asp.net so for instance:
try
{
zOrder = Session["epdqOrderNo"].ToString();
zAmount = Session["epdqAmount"].ToString();
zEmail = Session["epdqEmail"].ToString();
}
catch
{
}
Some or all of the session variables may exist and I'm trying to check them all but it appears that the try/catch routine goes into the catch on the first exception that it finds. So in the above example if the session variable epdqAmount doesn't exist it won't try and check for epdqEmail as its already fell out the try part. So my question is is there any way to stop this behaviour and check all of the variables or should I be using something else?

You're getting the error because Session["foo"] will return null is there is no session state variable called foo, and you can't call ToString() on a null reference.
However, you can use Convert.ToString on a null reference (in which case it will simply return string.Empty), so you could try this instead:
zOrder = Convert.ToString(Session["epdqOrderNo"]);
zAmount = Convert.ToString(Session["epdqAmount"]);
zEmail = Convert.ToString(Session["epdqEmail"]);
Using this approach, no try...catch is required because exceptions won't get thrown if any of the session variables don't exist.

You generally shouldn't try...catch in this manner, you could be potentially hiding other problems in your code. Whenever you use a try...catch try to be more specific with the exception it is you are after e.g.
try
{
}
catch (ErrorICanHandle ex)
{
}
Although in your case you would be listening for a NullReferenceException which is an indicator that you should really be checking that directly in the code as you would be effectively using exceptions to control your application flow which isn't a good idea.
As to your code, assuming all your session values are of type string then all you need is a straight cast
zOrder = (string)Session["epdqOrderNo"];
zAmount = (string)Session["epdqAmount"];
zEmail = (string)Session["epdqEmail"];
string is a special type of value type which inherits from object so this would just leave your variable as null if there is nothing in the session and not throw an exception.

try this
if(Session["MyDataSet"] == null)
{//something}
else
{//something}

In general, you'd write 3 try/catch blocks.
Couple of notes though:
You shouldn't be using a catch-all block. You might end up swallowing other important exceptions
In your particular case, there are other ways to check whether the session has those variables without throwing an exception, such as a simple null check (Session["epdqOrderNo"] == null), so I wouldn't even use try/catch here.

You can assign "" if they are null as follows using ?? as follow
zOrder = Session["epdqOrderNo"]??"";
zOrder = (string) (Session[""] ?? "");

Related

Do we get any benefit from adding null check if we are already using catch all Exception handler?

This is specific to .NET
I am writing a code piece where I have to use catch all exception handler. I call a series of function which may return null. I do not want to continue if any of them return null as I have an alternate but costly method to get the same result. I want to know if I should be using the series of null checks or not.
My code looks something like:
var some_info = null;
try{
var a = GetA();
if(a != null){
var b = a.GetB();
if(b != null){
var c = GetC(b);
if(c != null){
some_info = c.GetSomeInfo();
}
}
}
catch(Exception e){
// cant do anything here but I need above code to be silent
}
if(some_info == null)
some_info = GetSomeInfoFromHeavyMethod();
in C# if we try to use null reference it throws an exception so if any of the variables above will be null a NullReferenceException will be thrown. Therefore we can write the above code like
var some_info = null;
try{
var a = GetA();
var b = a.GetB();
var c = GetC(b);
some_info = c.GetSomeInfo();
}
catch(Exception e){
// cant do anything here but I need above code to be silent
}
if(some_info == null)
some_info = GetSomeInfoFromHeavyMethod();
My question is, should I use null checks here or let exception handler work here? My gut feeling says I should use the null check as it is good practice but, I have a doubt as I have to use catch all exception handler here and I already have to bear cost of try/catch block.
Yes, I would strongly advise using null checks:
It shows that you expect that the values can be null, and that that in itself is not a problem
If you ever add logging in your catch block, you can easily do so without being spammed by easily-avoidable messages
When debugging the code, you really don't want to end up with the debugger stopping for a NullReferenceException due to just not doing checks
You say that you "already have to bear cost of try/catch block" - it's not clear whether you're talking about the code readability cost or performance cost, but there's basically no performance cost for a try/catch block if no exception is thrown. Compare that with the case when an exception is thrown, which definitely has performance implications.
Ultimately, I'd consider every NullReferenceException to be a bug somewhere - it's the kind of exception that should always cause you to either add more validation (e.g. to throw ArgumentNullException) or handle the value being null. That wouldn't the case in your code.
With some refactoring you may be able to use the null-conditional operator introduced in C# 6 to reduce the code though. You might end up with:
someInfo = GetA()?.GetB()?.GetC()?.GetSomeInfo();
Exceptions are supposed to be thrown when exceptional situations occur. So, it all depends on whether you want to consider the case of a function returning null exceptional or not. There is no hard rule.
Though I would suspect that if the functions are returning null instead of throwing an exception, then a certain choice has already been made, by those who implemented those functions, that the situation is not exceptional. But of course at the place where you call these functions you may want to redefine what is exceptional and what isn't.
There is, however, a little technical issue: throwing an exception is extremely know on Microsoft's implementation of C#, (possibly also on Mono? I don't know) so we unfortunately tend to favor not considering certain situations exceptional (and therefore not throwing an exception) when the choice is borderline and performance is an issue.

Is it possible to continue running code from the point of failure?

Okay, I have some very simple code which I will post below. Essentially, I have a connection to a database and I want to map a subset of columns in a query to a particular class. The problem is that it is possible for these to be null.
I would like to know if it is possible if an exception is thrown at a particular line, can we resume the entire block from the next line.
So if this code below was to execute and Line 6 catches an error. Is there an elegant way to catch the exception and make the code resume running at line 7. Essentially making it as though line 6 was never executed.
private static Column MapTableToColumn(OracleDataReader reader){
Column c = new Column();
c.ColumnName = Convert.ToString(reader["COLUMN_NAME"]);
c.DataType = Convert.ToString(reader["DATA_TYPE"]);
c.DataLength = Convert.ToInt32(reader["DATA_LENGTH"]);
c.DataPrecision = Convert.ToInt32(reader["Data_Precision"]);//<---Line 6
c.DataScale = Convert.ToInt32(reader["Data_scale"]);//<--- Line 7
c.AllowDBNull = Convert.ToBoolean(reader["ALLOW_DB_NULL"]);
c.IsReadOnly = Convert.ToBoolean(reader["IS_READ_ONLY"]);
c.IsLong = Convert.ToBoolean(reader["IS_LONG"]);
c.IsKey = Convert.ToBoolean(reader["IS_KEY"]);
c.KeyType = Convert.ToString(reader["KEY_TYPE"]);
c.IsUnique = Convert.ToBoolean(reader["IS_UNIQUE"]);
c.Description = Convert.ToString(reader["DESCRIPTION"]);
return c;
}
It is important to note I am not asking for best practice, it is not something I intend to use in actual code (unless its absolutely genius). I simply want to know if this is possible and how one would go about doing this if it were.
My Research
Most of my research is proactive as opposed to reactive. I would attempt to know if it is possible for the given field to be null before it is read from. If it is, then I'd do a check to determine if the field is null and then set it to a default value. It essentially avoids the possibility of an error happening which I believe is a very good solution. I just wanted to attempt this as I know that when an exception is thrown, the most inner exception contains the line number at which it was thrown. Based on this if you put the exception inside of the class throwing the exception you should hypothetically be able to use reflection in order to continue running from its last point. I'm just not sure how you'd go about doing this. I've also considered the possibly of putting try catches around every single line which I think would be very effective; however, I think that it would be very ugly.
No, what you are asking for is not possible in C#.
Instead the proper solution to this problem is to use better parsing methods that won't throw exceptions in the first place. If your input values can be null, then use parsing methods that can accept null values.
The first thing you probably need to do is use nullable types for your int/bool fields, so that you can support null values. Next, you'll need to create your own methods for parsing your ints/bools. If your input is null, return null, if not, use int.TryParse, bool.TryParse (or as for each if your input is the proper type, just cast to object).
Then by using those methods, instead of Convert, you won't be throwing exceptions in the first place (which you shouldn't be doing here even if it could work, because exceptions are for exceptional cases, not expected control flow).
If the exception is expected then it is not exceptional. Never never never catch a null reference exception. A null reference exception is a bug. Instead, write code to avoid the bug.
You can easily write helper methods that test for null, or use methods like Int32.TryParse that can handle malformed strings.
Check for IsDBNull
SqlDataReader.IsDBNull Method
And Reader has methods for each SQL datatype
For example
SqlDataReader.GetSqlBoolean
If the data is in SQL as string (char,nchar) then first check for null and then TryParse
For example
DateTime.TryParse
And ordinal position is faster
This is a sample for a nullable Int16
Int16? ID;
ID = rdr.IsDBNull(4) ? (Int16?)null : rdr.GetInt16(4);
If you want a default
Int16 ID;
ID = rdr.IsDBNull(4) ? 0 : rdr.GetInt16(4);
You'd need a try/catch around every single variable assignment, and you'd need to initialize all your Column instance values before you tried. This would be relatively slow.
As for reflection based on the line number: I wouldn't rely on the line number because one simple, innocent change to the code will throw it off completely.
I'd check for nulls specifically. If you expect them you can't hardly call them "exceptions". The method that does that is reader.IsDBNull. It takes the column index (not the column name) so you'll need to resolve the index using reader.GetOrdinal:
if (reader.IsDBNull(reader.GetOrdinal("Data_Precision"))) {
// It's null
} else {
// It's not null
}

Do I need to initialize a variable, even if I know it will be assigned before used?

In an ASP.NET MVC app, I have code that boils down to the following:
public ActionResult Test() {
string query;
try {
query = GenerateQueryString();
}
catch (Exception ex) {
ModelState.AddModelError("error", ex.Message);
}
... do additional validation ...
if (ModelState.IsValid) {
return RedirectToAction("Success?" + query);
}
return View(); // Show validation messages
}
The above code has a compile error ... query might not be initialized.
However, the logic in the code will clearly initialize query before using it.
What is the best way to resolve this issue?
The C# compiler is looking at your code and seeing that the value of the variable is initialized in a try block and is then used later on. It can see that a logical branch of execution exists where an exception is thrown, is caught, and then the subsequent code is executed with an uninitialized value.
The simplest way to stifle the error is to assign a default value to the field. null is sufficient. As you're adding the error to the MVC model state and are checking that value later on before accessing query, you shouldn't be in a situation when the default value will matter.
You are wrong, What if GenerateQueryString throws an exception? What will be the value of Query?
You might want to do a query = "Error"; or something in your catch block. This because appareantly you want the application to run if an exception in GenerateQueryString is thrown.
EDIT
I would recommend against presetting query with a default value. This because the meaning is different. A default value is different than a certain value at a certain moment. Doing so will also prevent the compiler from warning you when you create a new code path but forget to setup a value for query
If there is exception in the call to GenerateQueryString the value of query will be undefined.
Try
string query = string.Empty;
to have a definite assignment to the variable.
Alternatively, if an exception should abort the execution, this will work too:
string query;
try {
query = GenerateQueryString();
}
catch (Exception ex) {
ModelState.AddModelError("error", ex.Message);
return View();
}
The Code is NOT clearly initialized. When the GenerateQueryString() Method throws an Exception, no value will be set. You should set the String to null and check for null before you use it, als you don't break in the catch-block.
Just because YOU know that it will be initialized (it may not be by the way in your code), the COMPILER can't know that - it's called the Halting problem.
So the compiler errs on the side of caution, something .net does a lot (e.g., no fallthrough in switch..case).
The thing here is that local variables must be initialized before read - they won't be initialized by default and this prevents from bugs programmers often makes. Some time ago I was looking for the answer to this simple situation:
bool a = true, b;
if (a == true) //here everything is OK, because a is initialized
b = true;
if(b == false) //here you get an error, I thought b == false by default
return;
I found on stackoverflow deep explanations, why it works so(couldn't find at the moment which I was reading). But you can read Absence of evidence is not evidence of absence interesting article. Maybe it will explain what I tried to say :)
Resume:
In your case you need to initialize query or set variable in catch block
Just change the declaration of query in: string query = string.Empty;.
The problem is that query is initialised in the try block, but query is declared in the block above. You must initialise it at the top level block.
It could just be that your GenerateQueryString() throws an exception. Personally, I prefer to initialize my variables, just to be on the safe side. For this reason you might just initialize to query to:
string query = String.Empty;
It doesn't hurt to be on the safe side.

C# - How to use unassigned variable in try catch block

crmFactory.RegisterDemoAccount throws Exception. In order to use the variable res I need to initialize it.
Since AccountRegistrationResponse is not initializable, how can I declare res without getting compilation errors about using unassigned variables?
I can assign it to null, but I don't think this is a good programming approach.
AccountRegistrationResponse res /*=null*/;
try
{
res = crmFactory.RegisterDemoAccount(CrmConfigRepository.CrmOwnerUserId
, CrmConfigRepository.CrmOrganizationName
, CrmConfigRepository.CrmBusinessUnitName
, demo.getData());
}
catch (Exception e)
{
_log.Error("Cannot create demo account", e);
}
_log.Debug(res.getString());
You shouldn't try to continue your method after catching an unknown exception. Anything could have gone wrong and it makes no sense to assume that it's safe to continue. Only bad things can happen if you try.
Either return an error result, or better, just rethrow the original exception:
catch (Exception e)
{
_log.Error("Cannot create demo account", e);
throw;
}
Now the compiler can see that res will always be assigned after the try block completes successfully.
I understand your reluctance to assign res to null - it feels pointless, and therefore wrong. It is a common approach in situations like this, though, when an object is needed outside the block in which it's assigned. Assuming you're doing the right thing in assigning your variable in a try/catch block (and it's not an uncommon pattern, in many cases), I wouldn't worry about it.
However, what would happen if the assignment failed? The second logging call would try to dereference res, and throw a NullReferenceException. That's not good.
You need to put the logging line inside the try/catch so that the compiler knows that res has been initialised.
try
{
res = ...
_log.Debug(res.getString()); }
catch (Exception e)
{
_log.Error("Cannot create demo account", e);
}
It's THE right approach. Only thing, if null is a valid return value of RegisterDemoAccount, you could add a bool initialized = false that you set to true just after the RegisterDemoAccount.
Assign it to null, like you said, if you need it outside of try/catch. It's not bad way of programming.
but I don't think this is a good programming approach.
Why? If you don't initialise res and then RegisterDemoAccount(...) (or another expression before it) throws then res will not be assigned in the try statement.
Therefore execution could reach the final statement (after the catch block) with res unassigned.
The problem is the use of res in that last statement – the compiler can see it can get to this point without initialisation.

Whether to check for null

I know that you should always check incoming params to a method for null. But what if I have this scenario with a try/catch referring to a local variable. Do I really need to check for null below? Because it's gonna catch it anyway if it's null and the next line of code tries to use the refundResponse variable:
public string DoRefund(...)
{
try
{
......
string refundTransactionID = string.Empty;
......
RefundTransactionResponseType refundResponse = transaction.DoRefund(...);
if (refundResponse != null)
refundTransactionID = refundResponse.RefundTransactionID;
.....
}
catch (Exception ex)
{
LogError(ex);
return ex.ToString();
}
}
Remember I'm talking specifically about local variables and checking those inside a method, not incoming params to a method.
All I'm asking here is do I need to check for null before setting refundTransactionID or do I just set it without the if assuming that the compiler will handle and throw if it is null which will be caught and thrown back as a string to the caller in this case.
or should it be
if (refundResponse == null)
return null;
or just take the check out completely for this local variable assignment and then since in this case I have a try/catch I'm handling any exceptions picked up by the compiler naturally by returning the exception as a string to the caller (it was not my decision to send back a string, it was a requirement by my boss...so bypass that debate for now):
refundTransactionID = refundResponse.RefundTransactionID;
ultimately the rest of the code further down the line in the method is dependent on a valid refundTransactionID.
Exceptions are for exceptional conditions. If you can check for a continuable error, do so, please!
I know that you should always check
incoming params to a method for null.
No, not necessarily. What you should specify is the contract of your method. It's perfectly acceptable (and common) to specify that you'll throw a NullPointer/NullReferenceException for a null parameter. Then you don't need any checking.
You can also check for null, but this only makes sense if you can actually handle a null usefully (e.g. substitute a default value).
You should have to check for null in that instance. Your application logic should be able to handle these kind of situations, without the need for exceptions.
An alternative to testing is the Null Object pattern. Instead of returning Null, or a valid transaction, the transaction::DoRefund() method returns a null object: an object that offers the same interface as the RefundTransactionResponseType instances, but its methods do nothing. With this there is no need to test whether for Null.
The should be used wisely as this can easily hide problems.
No you don't need to check for null, there. That opens up another question, though, do you really need to check for null in incoming parameters?
Remember: that's a behavior. You have to test that behavior.
But if you can't continue at that point let the exception propogate.
No, doesn't look like you should check for null here. And I also wouldn't check for null for ALL incoming parameters (as your description suggests).
It's also odd that you're returning a transactionID as a string OR the message of an exception. How will the caller of this method know if an exception happened?
If you really want to log the exception, how about something like this:
public string DoRefund(...)
{
try
{
return transaction.DoRefund(...).RefundTransactionID;
}
catch (Exception ex)
{
LogError(ex);
throw ex;
}
}
You should check for null rather than letting the exception handling handle it. As leppie said, exceptions are for exceptional conditions not normal flow of control. If you know what issues can occur then you should gracefully handle them.
Another thing to keep in mind is the performance impact of exceptions. When the exception is thrown the JVM has to unwind the call stack. In your example the exception is then also logged. All of this takes time and is much slower than a simple "if" check.
I'd suggest checking for the null then doing some kind of soft error handling instead of just letting it catch and throwing an error message.
It depends on what it means to your program when (refundResponse == null). If this has some meaning, then it makes sense to report a more informative error. If it should never happen and would indicate a flaw in the DoRefund method, then I think it's fine to allow the null to cause an exception later. In the latter case, I'd only have a specific check if you're suspicious of the method and whether it's behaving as it's supposed to.

Categories

Resources