Handling a null exception C# - c#

Ok, new coder here looking for a little insight into this problem. So I have a for loop like that starts like this:
for (int i = 0; i < rowHandles.Length; i++)
{
.........code....
}
rowHandles is an int array that contains rows of data. This for loop has code that deletes the rows of data when a delete button is clicked, to be specific it is a grid tool strip Delete button and this is inside the delete button click event handler. The problem is the delete button can be clicked when there are no rows left, so rowHandles.Length is equal to null. How would I prevent this from stopping the program? Is there something I could add inside the for loop, in the for loop declaration, or outside the for loop to correct this? Maybe a try catch? How would this be structured around this specific problem/loop?
Thanks for all your help - Newbie Coder

If the problem is that rowHandles can be null then just add an explicit check for that which prevents you from executing the for statement.
if ( rowHandles != null ) {
for ( int i = 0; i < rowHandles.Length; i++ ) {
...
}
}
Another option would be to disable the delete button altogether if there are no rows to be deleted. The operation is invalid so prevent it from the start.

An important principle here is never handle an exception that you could have prevented in the first place. You should never ever ever handle a null reference exception; a null reference exception indicates a bug in your program that should be fixed, not an expected occurrance that should be trapped and ignored. Either write code that ensures that the value is not null, or detect that it is null and do not dereference it.

The problem is the delete button can be clicked when there are no rows left, so rowHandles.Length is equal to null.
This is wrong. When there are 0 elements, Length is set to 0. What is null is probably rowHandles. You need to handle that condition before you get into your loop.

If there are no rows left, rowHandles.Length will be zero not null. If you're getting rid of rowHandles after the loop, then you can just do:
if (rowHandles != null)
{
for (int i = 0; i < rowHandles.Length; i++)
{
// Code
}
}
No need for exception handling. On the other hand if you're allowing rowHandles to be changed by something else while that loop is running, that's another story.

It's not rowHandles.Length which is null, it's rowHandles itself.
A common solution would be:
if (rowHandles != null)
//Your loop here

It looks like Length is not the thin that is null. Rather it is rowHandles that is null and you are getting the null exception when trying to access the Length property.
if(rowHandles != null)
{
//for loop
}

I would suggest you try as much as possible to stick to the Single Responsibility Principle, in that you let the code do what it is intended to do, and handle the errors elsewhere.
It makes sense to me that rowHandles is used elsewhere, so you should centralize the process of checking whether or not it is null.
If you still choose to handle it in the code body you're referencing, any of the suggested solutions will work.

Change to a foreach loop:
foreach (var rowHandle in rowHandles)
{
// use rowHandle instead of rowHandles[i]
}
This way, provided the entire rowHandles object is not null (a quick null check can verify this) you will iterate over all items, and if there are no items, you wont iterate at all.

Related

Null reference exception stops the code execution inside of try block

So I have a code segment where I am expecting a method that is repeatedly called from inside a loop to return null at one point - null is returned because the table cell that this method tries to read from is empty. And that part is clear, that's not the problematic part of the behavior. Here is that part of code:
while (!String.IsNullOrEmpty(columnI_value))
{
typeOfShareLineCounter++;
try
{
columnI_value = sheet.GetRow(3 + typeOfShareLineCounter + typeOfShareStartIndexNewFile).GetCell(8).ToString();
}
catch
{
}
}
What I don't understand is why does program execution stop when an empty cell is reached in this case? I get NullReferenceException, but I am expecting the program to continue since the line of code where this exception occurs is inside the "try" block as you can see above.
Is it because of some Visual Studio setting?
As a side note, in a "normal" scenario, I could have probably just checked what the GetCell method returns and if it's null, just break out of the loop (because null in this case means that we have reached the end of the file segment that needs to be read).
However, GetCell here produces an exception in case the cell it is trying to read is empty. This is the reason I used the try-catch. But I was not expecting the program execution to halt in this case. At the moment, I do not see a way to handle the exception without it breaking the program. Btw, this problematic method (GetCell) is a part of the NPOI library for working with excel files.
Thanks a lot for your help.
Why don't you check if something is null before trying to access it?
I think GetCell throws an exception because GetRow returns null.
Also not clear what value is initially in columnI_value.
I would use something like this (just guessing what this code is expected to do):
typeOfShareLineCounter = 0;
while (true)
{
var cell = sheet.GetRow(3 + typeOfShareLineCounter + typeOfShareStartIndexNewFile)?.GetCell(8);
if (cell == null)
continue;
columnI_value = cell.ToString();
if (String.IsNullOrEmpty(columnI_value))
break;
typeOfShareLineCounter++;
}

Do I need to explicitly run an if statement before a while-loop?

I am fairly new to the C# language and wondered something when writing code not so long ago. When I am writing while loops, I also find asking myself do I explicitly need to check if my while condition is even needed, lets take the following code for example.
while (_myList.Count > 0)
{
// do some work
}
If previously written code (by other developers) I have seen them do something like this...
if (_list.Count > 0)
{
while (_myList.Count > 0)
{
// do some work
}
}
Which is the best practice, do I even need to do this? If so why.. can someone shine some light on this topic and let me know whats best? Thanks.
You don't have to specify the if:
if (_list.Count > 0)
While loop
What a while loop does: is taking an argument and compares whats left
from the operator to the the right. And returns a boolean (true or
false) as long the while gets a true it will continue the loop.
IF
What an if statment does: is taking an argument and compares whats left
from the operator to the the right. And returns a boolean (true or
false) as long the if gets a true it will continue and run the code in the if code block.
notice:
if (_list.Count > 0) // checking for _list
{
while (_myList.Count > 0) // checking for _myList
{
}
}
In the example you have shown the "Other developer" you check on different situations so in this case it can be usefull to check on _list.Count if you don't want to run te loop when _list.Count > 0.
Conclusion
Don't do: it when you checkking on teh same list in the if and wile.
Can do: if you only want to run the wile on an certain condition or possible exception.
No you don't need to add an if in this case.
Before entering while condition will be evaluated and you don't iterate if <= 0.
Caution in your sample you speak of _list and my_list which isn't the same object.
The second code example is useless. If list count is 0 or smaller, the while wouldn't be executed.
However, you have to check, if _myList is null, maybe like this:
if (_myList == null)
//error handling here
if _myList really was null, then you'd have a NullReferenceException in both your code examples.

Safe usage of .FirstorDefault()?

When using Enumerable.FirstorDefault(), do I need to always catch the ArumentNullException that can be thrown when the collection operated on is null?
In the past I've always just done something like this:
WorkflowColorItemType associatedColor = ColorItems
.Where(ci => ci.AssociatedState == WorkflowStateStatus.NotStarted)
.FirstOrDefault();
if (associatedColor != null)
{
this.ColorItems.CurrentColor = associatedColor;
}
In the context of this code snippet, I would never expect ColorItems to be null but is it good practice to be enclosing every instance of snippets like this in try catch blocks so I can handle the off chance that the ColorItems collection might be null?
If you don't expect the collection to ever be empty, and it would be an error in your program for it to be empty, then don't use FirstOrDefault in the first place, use First. Since it's not an expected situation for you to be in you want to draw attention to the problem because it's a sign that something is wrong.
If it's entirely valid for the collection to be empty, and you want to use the first item only if there is at least one item, then using FirstOrDefault and providing a null check is fine.
Apply the same logic to the collection being null, and not empty. If it is expected that the collection be allowed to be null, then check for it using an if. If it's not expected that the collection be allowed to be null (which is generally the case for most uses of collections) then you shouldn't check, and you want the exception to be thrown as it will draw attention to the bug in the code that is supposed to populate that collection. Trying to catch the exception and move on is trying to obscure the bug which prevents you from finding and fixing it.
Yes, certainly. You need to be defensive all the time.
In fact, if associatedColor is null, that means there is something wrong, hence you need to handle it.
In fact, your code used to be wrapped in a try/catch block to handle exceptions, since, exceptions are "expensive", this is cheaper and nicer way to handle exceptional cases.
In any case, I would almost always use FirstOrDefault or something simirlar, like SingleOrDefault then I would do the null check.
The built in LINQ functions (like .Where() here) always return an empty enumerable if there are no results, not null. So there is no need to check for null after doing the .Where()
Depending on where ColorItems comes from, you should check for null on the object:
if (ColorItems != null)
{
}
else
{
}
There's no need to put a try/catch block around the code, but you should be checking for null just to be safe. In fact, using try/catch in a scenario like this, where you can just check for a null object, is a bad programming practice.

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
}

How to set a view state in a master page?

I need to check whether an event is fired from the master page or not. For that i kept a count in the viewstate . This is throwing exception on page load. I'm just calling the below line in a pageload
Int32 count = Int32.Parse(this.ViewState["Count"].ToString());
Please help.
This will throw an exception in a few cases.
The key "Count" isn't in the view state yet. ViewState["Count"] will return null and the .ToString() call will throw a NullReferenceException.
The value of "Count" can't be parsed into an int, throwing a FormatException.
Things to try:
You should check the ordering of your code to make sure that you are setting the value of count before attempting to read from it.
Your code can be improved as follows:
Int32 count;
string countStr = this.ViewState["Count"];
if(!string.IsNullOrEmpty(countStr )
{
bool ok = Int32.TryParse(countStr, out count);
if(ok)
{
// Do stuff with count
}
}
You might consider using the Session rather than the ViewState to store custom data between pages.
<pagesenableSessionState="false"enableViewState="false"theme="Default" />
Make sure that ViewState["Count"] exist before performing operations to avoid exceptions.
Use this code to default the count value to 0:
Int32 count = Int32.Parse((this.ViewState["Count"] ?? "0").ToString());
This will stop you seeing an Exception if the "Count" key doesn't exist in the ViewState collection.

Categories

Resources