Reputation: 3000
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 asTryParse
or subsequentIf
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
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
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
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
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