C# 获取解析失败的实际值

C# 获取解析失败的实际值,c#,try-catch,C#,Try Catch,免责声明这个问题是关于,如果和如何我们可以使用解析方法异常,来查找转换失败的参数/变量。争论这是最好的还是正确的方法是而不是TryParse或后续if语句。然而,每一种备选方案或解决办法都值得赞赏 我有下面的C代码块# 这里的intb1=int.Parse(b)行将失败,catch块将捕获异常 是否可以通过编程方式检查异常信息,找到导致错误的实际值(字符串b的值,而不是变量的名称)。例如,我想得到如下结果: 无法分析“b” 不可靠-在FormatException中没有任何内容可以为您做到这一点

免责声明这个问题是关于,如果如何我们可以使用
解析
方法异常,来查找转换失败的参数/变量。争论这是最好的还是正确的方法是而不是
TryParse
或后续
if
语句。然而,每一种备选方案或解决办法都值得赞赏

我有下面的C代码块#

这里的
intb1=int.Parse(b)行将失败,catch块将捕获异常

是否可以通过编程方式检查
异常
信息,找到导致错误的实际值(字符串b的值
,而不是变量的名称)。例如,我想得到如下结果:

无法分析“b”


不可靠-在
FormatException
中没有任何内容可以为您做到这一点。解析消息是非常脆弱的-它可以在不同版本的.NET中更改,并且将被本地化

一个选项是编写自己的
Parse
方法,该方法可与
int.Parse
互操作,但会抛出
FormatException
的子类。例如:

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);
    }
}
然后您可以将其用作:

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}");
}
改用TryParse(您不需要整个try-catch),例如:

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
}

这个简单的图案怎么样

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)}");
}

我们使用这种模式(主要是为了避免本地化消息和中性日志消息的切换/大小写,为了简单起见,这里没有显示,否则@JonSkeet的解决方案创建自定义异常并调用包装器方法是正确的方法):

其思想是在做某事之前设置原因(可以选择在做某事之后清除),如果失败,则执行-向用户显示原因


有些东西可以是任何一段代码,因此我不想通过建议
TryParse

来改进解析,我会用
TryParse
来解决它-这种方法有什么问题?
TryParse
不是一种“变通方法”但唯一可靠的方法是另一种选择是将其实际拆分为多个
try catch
块,以便您确切知道失败的原因,但是我真的不认为在这里避免
TryParse
有什么意义。我想他想知道在他的
Exception e
中是否有关于变量名的信息-我认为这不是你可以编写自己的解析方法(wrapper-around int.parse)这将提供有关异常中失败值的信息。这将是我首选的解决方案。在这种情况下没有必要进行异常处理。@DanWilson我也这么想:D Jon正在用大锤敲开一颗坚果。回答得很好,但正如我所说的,我知道如何“用这种方式”来做。我只是在寻找替代方案,如果我能通过
Parse
Exceptions
@Athafoud实现这一点:是的,其他答案证明了存在替代方案,但是。如果你在解析一个字符串,那么我认为假设它可能不是一个整数是公平的。异常处理是过火了,IMHO。答案很好,但正如我所说的,我知道如何“以这种方式”处理。我只是在寻找替代方案,如果我能通过
Parse
Exceptions
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)}");
}
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);
}