Home > Back-end >  How to exit method from sub-method without throwing exception
How to exit method from sub-method without throwing exception

Time:12-18

I have the following code, but I am not sure what is the right pattern to exit the Execute() method.

The code is working, but the Execute() method is too large.

public void Execute()
{
    // load datatable from excel
    DataTable data = new();
    try
    {
        data = ExcelReader.ToDataTable(_meta.FullPath, new() { SheetName = _sheetName });
    }
    // these errors are fine, but the dataset is not relevant and we want exit the execution
    catch (ArgumentOutOfRangeException e)
    {
        if (e.Message.Contains("HeaderRowIndex")) return;
    }
    catch (ArgumentNullException e)
    {
        if (e.Message.Contains("Parameter 'sheet'")) return;
    }

    // execute logic on dataset
    // ..
}

I would like to move the load data part of the code into separate method like this, but then I don't know how to end the execution.

public void Execute()
{
    // load data
    DataTable data = new();
    LoadData();

    // execute logic on dataset
    // ...
}

private DataTable LoadData()
{
    try
    {
        data = ExcelReader.ToDataTable(_meta.FullPath, new() { SheetName = _sheetName });
    }
    // these errors are fine, but the dataset is not relevant and we want exit the execution => but how?
    catch (ArgumentOutOfRangeException e)
    {
        if (e.Message.Contains("HeaderRowIndex")) return; // will return to Execute() method, but not exit it.
    }
    catch (ArgumentNullException e)
    {
        if (e.Message.Contains("Parameter 'sheet'")) return; // will return to Execute() method, but not exit it.
    }
}

I think this is very common issue, so what is the recommended way to handle this requirement? Should I create some returning object from the LoadData method, for example

class LoadDataResult
{
    public DataTable data {get; set};
    public bool IsRelevant {get; set};
}

dataResult = LoadData()
if (!dataResult.IsRelevant) return;

or it is an overkill and easier solution exist (to not populate program with these result objects)?

CodePudding user response:

You can return data in the output parameter and return result of data loading as a primary method output (true for successful load, false for error that is fine):

 private bool TryLoadData(out DataTable data)
 {
    data = null;

    try
    {
        data = ExcelReader.ToDataTable(
           _meta.FullPath, new() { SheetName = _sheetName });
        return true; // loading succeeded
    }        
    catch (ArgumentOutOfRangeException e)
        when (e.Message.Contains("HeaderRowIndex"))
    {         
        // loading failed, continue to Execute method
        return false;
    }
    catch (ArgumentNullException e)
        when (e.Message.Contains("Parameter 'sheet'"))
    {
        // loading failed, continue to Execute method
        return false;
    }

    // otherwise exception propagates to Execute method
 }

Usage:

public void Execute()
{
    if (TryLoadData(out var data)
    {
       // execute logic on dataset
    }
    else
    {
       // error, but not exception
    }
}

CodePudding user response:

I would think about what you are trying to return. In your catch's you can log the error but you don't need to return. All code will flow back to the previous method that called it regardless if it returns or not. You only need to return if you need to pass a value back up to the previous calling method. Otherwise, you can just leave it be!

  • Related