Athafoud
Athafoud

Reputation: 3000

Get the actual value that failed the Parse

Disclaimer This question is about, If and How we can use the Parse method exceptions, to find which argument/variable had actually failed the conversion. It is NOT, to argue if this is best or the correct way neither to find alternatives such as TryParse or subsequent If statements. However, each and every alternative or workaround is appreciated.

I have the following code-block in C#

string a = "1"
string b = "b"
string c = "3"

// add many more similar

try 
{
    int a1 = int.Parse(a);
    int b1 = int.Parse(b);
    int c1 = int.Parse(c);
}
catch (Exception e)
{
    // Here I will do some logging
}

Here the int b1 = int.Parse(b); line will fail and catch block will catch the exception.

Is it possible by examining, programmatically, the Exception info, to find the actual value (the value of string b, not the name of the variable) that caused the error. For example I would like to get something like:

Could not parse "b"

Upvotes: 0

Views: 324

Answers (4)

Sinatr
Sinatr

Reputation: 22008

We are using this kind of pattern (mainly to avoid switch/case for localized messages and neutral logger message, not shown here for simplicity, otherwise solution of @JonSkeet with creating custom exception and calling wrapper method is the right way):

string problem = null;
try
{
    problem = "Can't parse a";
    var a1 = int.Parse(a);

    problem = "Can't parse b";
    var b1 = int.Parse(b);

    problem = "Can't parse c";
    var c1 = int.Parse(c);

    problem = "Can't do something";
    ... // something
}
catch(Exception e)
{
    Logger.Add(e);
    UserMessage(problem);
}

The idea is to set reasons prior doing something (optionally clear it after), do it, if it fails - display reason to the user.

Something can be any piece of code, therefore I am not trying to improve parsing specifically by suggesting TryParse.

Upvotes: 0

Andrei Filimon
Andrei Filimon

Reputation: 1188

Use TryParse instead (you don't need the overall try catch), example:

int a1=0;
if(!int.TryParse(a, out a1))
{
    //do something here
}
int b1=0;
if(!int.TryParse(b, out b1))
{
    //do something here
}
int c1=0;
if(!int.TryParse(c, out c1))
{
    //do something here
}

Upvotes: 6

Hossein Narimani Rad
Hossein Narimani Rad

Reputation: 32521

What about this simple pattern

string a = "1";
string b = "b";
string c = "3";

int aInt, bInt, cInt;

if (!int.TryParse(a, out aInt))
{
    //report e.g.
    Console.WriteLine($"Could not parse {nameof(a)}");
}

if (!int.TryParse(b, out bInt))
{
    //report e.g.
    Console.WriteLine($"Could not parse {nameof(b)}");
}

if (!int.TryParse(c, out cInt))
{
    //report e.g.
    Console.WriteLine($"Could not parse {nameof(c)}");
}

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1503669

Not reliably - there's nothing in the FormatException that does this for you. Parsing the message is very fragile - it can change in different versions of .NET, and it'll be localized.

One option would be to write your own Parse method which is interoperable with int.Parse, but throws a subclass of FormatException. For example:

public class ParseException : FormatException
{
    public string OriginalValue { get; }

    public ParseException(string message, string originalValue)
        : base(message)
    {
        OriginalValue = originalValue;
    }
}

public class ExtendedParsing
{
    public int ParseInt32(string value)
    {
        int result;
        if (int.TryParse(value, out result))
        {
            return result;
        }
        throw new ParseException($"Unable to parse \"{value}\"", value);
    }
}

Then you can use it as:

try 
{
    int a1 = ExtendedParsing.ParseInt32(a);
    int b1 = ExtendedParsing.ParseInt32(b);
    int c1 = ExtendedParsing.ParseInt32(c);
}
catch (ParseException e)
{
    Console.WriteLine($"Value that I failed to parse: {e.OriginalValue}");
}

Upvotes: 5

Related Questions