如何在catch中使用try中的对象 - c#

时间:2017-04-26 14:17:24

标签: c# exception

我想在catch块中使用一个对象,这会在try块中产生异常。我将一些字符串解析为int并且需要在不可能的情况下捕获异常,并查看错误的对象以及在哪一行。这可能与否?

一些代码示例。感谢。

static void Main(string[] args)
{
    var result = Parse(new List<string>() { "3;5;7", "qwe;3;70" });
}

public static List<int[]> Parse(List<string> list)
{
    try
    {
        return list.Select(str => str.Split(';'))
            .Select(str => Tuple.Create(int.Parse(str[0]), int.Parse(str[1]), int.Parse(str[2])))
            /// something happening
            .ToList();
    }
    catch
    {
        //here in braces I want to know, which element was wrong
        //"qwe" and whole line "qwe;3;70"
        throw new FormatException($"Wrong line [{}]");
    }
}

6 个答案:

答案 0 :(得分:1)

声明try/catch块之外的行和值项计数器,并在LINQ表达式主体中增加它们:

public static List<int[]> Parse(List<string> list)
{
    int line = 0;
    int item = 0;
    try
    {
        return list
            .Select(str => {
                line++;
                item = 0;
                return str
                    .Split(';')
                    .Select(i => { item++; return int.Parse(i); })
                    .ToArray();
            })
            .ToList();
    }
    catch
    {
        throw new FormatException($"Wrong line [{line}]; item [{item}]");
    }
}

演示:https://dotnetfiddle.net/uGtw7A

答案 1 :(得分:1)

您需要引用导致异常的对象。但是,由于实例仅存在于try-block的范围内,因此您无法再访问它(尝试捕获并不共享相同的范围,因此无法访问相同的变量),除非您声明引用到try-bloc之外的那个实例

正如评论中已经提到的,您应该使用正常的foreach - 循环来访问当前行:

public static List<int[]> Parse(List<string> list)
{
    var result = new List<int[]>();
    foreach(var str in list)
    {
        try 
        {
            var values = str.Split(';');
            result.Add(Tuple.Create(
                        int.Parse(values[0]), 
                        int.Parse(values[1]), 
                        int.Parse(values[2]))
                    );
        }
        catch
        {
            //here in braces I want to know, which element was wrong
            throw new FormatException($"Wrong line " + str");
        }
    }
    return result;
}

但是,您可以通过使用TryParse来避免所有这些异常,如果解析失败则返回false。所以这归结为这样的事情:

var values = str.Split(';');
int v0, v1, v2;
if(int.TryParse(values[0], out v0 &&
        int.TryParse(values[1], out v1 &&
        int.TryParse(values[2], out v2 &&))
   result.Add(Tuple.Create(v0, v1, v2));
else
    throw new FormatException($"Wrong line " + str");

答案 2 :(得分:1)

我建议手动循环,分割数据,检查是否有足够的元素,然后在数字上使用TryParse。我知道这与使用Linq有所不同,但这是通过错误检查执行此操作的更好方法:

public static List<int[]> Parse(List<string> list)
{
    if (list == null)
    {
        throw new ArgumentNullException("list");
        // you can use nameof(list) instead of "list" in newer versions of C#
    }

    List<int[]> result = new List<int[]>();
    // Loop through the entries
    for (int i = 0; i < list.Count; ++i)
    {
        // Be safe and check we don't have a null value
        // I'm just skipping the 'bad' entries for now but
        // you can throw an error, etc.
        if (list[i] == null)
        {
            // do something about this? (an exception of your choosing, etc.)
            continue;
        }

        // split the entry
        string[] entryData = list[i].Split(';');
        // check we have 3 items
        if (entryData.Length != 3)
        {
            // do something about this?
            continue;
        }

        // try to parse each item in turn
        int a;
        int b;
        int c;

        if (!int.TryParse(entryData[0], out a))
        {
            // do something about this?
            continue;
        }

        if (!int.TryParse(entryData[1], out b))
        {
            // do something about this?
            continue;
        }

        if (!int.TryParse(entryData[2], out c))
        {
            // do something about this?
            continue;
        }

        // add to the results list
        result.Add(new int[] { a, b, c });
    }

    // return the result
    return result;
}

答案 3 :(得分:0)

范围是范围。您在try区块内定义但未明确传递的任何内容都无法在catch区块中显示。

如果您需要此信息,则必须在列表上手动迭代并尝试单独捕获每次尝试...

答案 4 :(得分:0)

您的代码存在太多问题,您假设参数list不为空并且包含可以在3个字符串中拆分的项目,并且每个字符串都可以安全地解析为{{ 1}}。

如果您没有上述所有保证,请检查所有内容:

int

答案 5 :(得分:0)

我认为你这里的方法错了。是的,使用Tuple + Linq将是获得结果的最懒惰的方法,但是你不能生成自定义错误。

以下是一个如何实现相似内容的示例:

    static void Main(string[] args)
    {
        var result = Parse(new List<string>() { "3;5;7", "qwe;3;70" });
    }

    public static List<Tuple<int, int, int>> Parse(List<string> list)
    {
        List<Tuple<int, int, int>> result = new List<Tuple<int, int, int>>();
        int line = 0;
        int errorCol = 0;

        try
        {
            for (line = 0; line < list.Count; line++)
            {
                string[] curentLine = list[line].Split(';');
                int result0, result1, result2;
                errorCol = 1;

                if (curentLine.Length > 0 && int.TryParse(curentLine[0], out result0))
                    errorCol = 2;
                else
                    throw new Exception();

                if (curentLine.Length > 1 && int.TryParse(curentLine[1], out result1))
                    errorCol = 3;
                else
                    throw new Exception();

                if (curentLine.Length > 2 && int.TryParse(curentLine[2], out result2))
                    result.Add(new Tuple<int, int, int>(result0, result1, result2));
                else
                    throw new Exception();
            }

            return result;
        }
        catch
        {
            //here in braces I want to know, which element was wrong
            throw new FormatException("Wrong line " + line + " col" + errorCol);
        }
    }

PS:行和列从0开始。