0

so currently i am writing a program something like this:

try
{
    mainprocessing();
}
catch (exception e)
{
    //first catch block.
    //do something here
}

mainprocessing()
{
    try
    {
        string value = ReadCell.ReadCellValue(allEmployeeTimesheet[i], "Sheet1", "A1"); //I am calling ReadCellValue() method to check the value of A1 cell of an excel spreadsheet and if it is null, it will be handled in the following catch block.
    }
    catch (NullReferenceException e) 
    {
        //second catch block
        //something here to handle it
    }
}

But when I run the program now, if string value is null, the exception will be handled in the first catch block. However I want it to be handled in the second catch block. Is there any way to manipulate this?

Peter Ritchie
  • 35,463
  • 9
  • 80
  • 98
OPK
  • 4,120
  • 6
  • 36
  • 66
  • 2
    You really should not use exception to control the flow. Check the value instead. – VMAtm Mar 12 '15 at 12:25
  • You need to also catch the `NullReferenceException` in the "second" try/catch – Russ Cam Mar 12 '15 at 12:25
  • @RussCam sorry I am new to c#, i changed it to `NullReferenceException`, is it correct now? – OPK Mar 12 '15 at 12:26
  • @taimeili123 compile and run the code and find out :) – Russ Cam Mar 12 '15 at 12:27
  • @VMAtm Could you please provide more detail on "check the value instead"? I want to make sure I understand – OPK Mar 12 '15 at 12:29
  • 2
    `if (value != null)` - simple check – VMAtm Mar 12 '15 at 12:30
  • Set a debug point ( the red one in the left in Visual Studio) in the line string value = ReadCell.ReadCellValue(allEmployeeTimesheet[i], "Sheet1", "A1"); then run the code and set the pointer oof your mouse in "value" and check if it gets a value or not. – U. Busto Mar 12 '15 at 12:33
  • replace your `string value=....` with `throw new NullReferenceException();` for a while and check if it is handled there because I think it is.The problem is something else – Rohit Mar 12 '15 at 12:33
  • @VMAtm the problem is i cannot simply use `if (value != null)` in this case because i am actually calling `ReadCellValue()` method from `ReadCell` class and when I call this method if the cell value is `null`, it will be an exception in the `ReadCellValue()` method and it is automatically propagate to the `first catch block`. – OPK Mar 12 '15 at 13:00

3 Answers3

0

Didn't read the question the proper way, was thinking you want to get explicit into the top level exception.

When a value is null and trying to access this variable, there will be no reference to an actual object and so an NullReferenceException will be thrown but in this case you are allocating value to an reference so there is another exception thrown rather than NullReferenceException.

The only way to found out which Exception is been thrown, add another catch block below the NullReferenceException.

catch (NullReferenceException e) 
{
    //second catch block
    //something here to handle it, LOG IT!
}
catch (Exception exception)
{
    Type exceptionType = exception.GetType();
}

When an Exception has been handled(catched) by the program it returns to the point where this function has been invoked, in this case 'mainprocessing'.

If you explicit WANT to get into the most top level Exception handling block, just throw a new Exception inside the catch, like this:

mainprocessing()
{
    try
    {
        string value = ReadCell.ReadCellValue(allEmployeeTimesheet[i], "Sheet1", "A1"); //I am calling ReadCellValue() method to check the value of A1 cell of an excel spreadsheet and if it is null, it will be handled in the following catch block.
    }
    catch (NullReferenceException e) 
    {
        //second catch block
        //something here to handle it, LOG IT!
        throw new Exception("top level exception");
    }
}
Kevin
  • 506
  • 6
  • 13
  • It should be `throw new Exception("top level exception", e);`, it's bad practice and generally bad habbit to lose the original exception. – bokibeg Mar 12 '15 at 12:45
  • That is totally correct! And yes this is a great example how to approach this differently. – Kevin Mar 12 '15 at 12:55
0

As mentioned in the comments handling exceptions is not the way to handle flow control in C#. You use them if something unexpected happens, something you are not able to check in advance, before starting your process (e.g. file is corrupted and your read is aborted unexpectedly).

In your case just go with simple if check:

string value = ReadCell.ReadCellValue(allEmployeeTimesheet[i], "Sheet1", "A1");

if (string.IsNullOrWhiteSpace(value))
{
    // Handle the null/empty string here.
    // From what you said probably the logic you wanted to use in your second catch block.
}

EDIT:

To handle the exception on the level of ReadCell just check if it's null before accessing the value. Then you have a couple of options. You can abort the execution (return) or try to get an instance of ReadCell.

if (ReadCell == null)
{
     // abort the execution, create 
}

string value = ReadCell.ReadCellValue(allEmployeeTimesheet[i], "Sheet1", "A1");

Alternatively just indent several ifs:

if (ReadCell != null)
{
    string value = ReadCell.ReadCellValue(allEmployeeTimesheet[i], "Sheet1", "A1");

    if (string.IsNullOrWhiteSpace(value))
    {
        // Handle the null/empty string here.
        // From what you said probably the logic you wanted to use in your second catch block.
    }
}
else
{
    // Handle null case for ReadCell.
}
PiotrWolkowski
  • 8,408
  • 6
  • 48
  • 68
  • The problem is `ReadCell.ReadCellValue()` is in the class `ReadCell` and if i use `if (string.IsNullOrWhiteSpace(value)) ` , a `nullreference exception` will not be handled so the program will propagate the exception to the outer `catch` block – OPK Mar 12 '15 at 12:49
  • I've edited my answer to adjust it to ReadCell null case – PiotrWolkowski Mar 12 '15 at 14:32
0

Here's how you should handle exceptions in your specific scenario:

    private void btnDataStuff_Click(object sender, EventArgs e)
    {
        try
        {
            ProcessSomeData();
        }
        catch (Exception ex)
        {
            MessageBox.Show("Error: " + ex.Message);
            MessageBox.Show("Inner exception: " + ex.InnerException.Message);
        }
    }

    private void ProcessSomeData()
    {
        try
        {
            // Code where NullReferenceException exception happens
        }
        catch (NullReferenceException ex)
        {
            throw new ApplicationException("Data is null!!!", ex);
        }
    }

This is the proper way to handle and propagate your exceptions. I think this is what you originally wanted to accomplish. If NullReferenceException exception happens in the ProcessSomeData method - it will be propagated as a new exception with Data is null!!! message but it will also keep the original exception because it stores critical information for later debugging (call stack among other things). This way, you can have "nice" error messages in your application for the end user and original exceptions for the programmer to debug if needed.

This is a very simple example though. Please read this to learn best practices when handling exceptions. It's one of the most important aspects of programming that you will (have to) learn - you will eventuall learn it either way but why take the hard path when you can make your life easier from the start.

Also read up on C# coding conventions so you can write quality code from the start.

Other posters hinted that you should validate your data for null instead of catching exceptions and in most cases this is true but in case you still do want to catch some specific exceptions you now know a proper way to do so.

Community
  • 1
  • 1
bokibeg
  • 2,081
  • 16
  • 23
  • 1
    also you can implement your own Exception type, and don't use the `Exception` class, only the `ApplicationException` – VMAtm Mar 12 '15 at 14:03
  • You're very right, I've edited the answer to include `ApplicationException`. Thanks for the hint! – bokibeg Mar 12 '15 at 15:17