为什么我的代码在“using”语句外面是不可达的?

3
如果在使用语句中抛出异常,它应立即调用 finally 块并处理对象的释放。因此,try 块的其余部分不应执行,对吗?
 public static async Task<bool> AddCharName(string id, string name)
        {
            using (var dbConn = new DbConn())
            {
                await dbConn.Connection.OpenAsync();

                command = "UPDATE user SET name = @name WHERE name IS NULL AND id = @id";

                using (MySqlCommand update = dbConn.Connection.CreateCommand())
                {
                    update.CommandText = command;
                    update.Parameters.Add("@name", MySqlDbType.VarChar).Value = name;
                    update.Parameters.Add("@id", MySqlDbType.VarChar).Value = id;
                    await update.ExecuteNonQueryAsync();
                    return true;
                }
            }
            return false;
        }

在我的例子中,return false会给出“检测到无法访问的代码”警告。我是否正确地将其视为错误?如果在using (MySqlCommand upd...中抛出错误,那么它应该返回false,对吗?

你没有 try 块。 - Deolus
“using” 实际上是一个 “try finally” 块,不是吗? - Buretto
5个回答

3

非常简单...

总是返回自

return true;

它从未有机会到达。
return false;

这是编译器最了解的情况

更新

你确定吗?所以如果在使用语句中发生异常,在返回true之前它仍然会返回true吗?

虽然using实现了try finally,但它仍然抛出原始的异常,因此永远不会到达return false;(无论发生什么)。


你确定吗?所以如果在using语句中发生异常,在“return true”之前它仍然会返回true吗? - Buretto
1
@Bureto 不,它会崩溃,因为你的异常将无法处理。 - Loocid

3

using是一种语法糖,它相当于使用try-finally语句块而没有catch块。换句话说,你有:

MySqlCommand update = dbConn.Connection.CreateCommand();
try
{
    update.CommandText = command;
    update.Parameters.Add("@name", MySqlDbType.VarChar).Value = name;
    update.Parameters.Add("@id", MySqlDbType.VarChar).Value = id;
    await update.ExecuteNonQueryAsync();
    return true;
}
finally
{
    update.Dispose();
}

注意没有catch,所以你的代码会做以下两件事之一:

  1. 执行到return true;并返回。
  2. 抛出异常。然后finally块会被执行以释放对象,异常随即向调用者冒泡(如果没有处理程序,则崩溃)。

在两种情况下,执行都不会超过return true;语句。当然,对于外部的using块也是如此。


现在,你最可能想要做的是捕获发生的异常。快速而简单的方法是将所有内容都包装在try-catch中,但根据应用程序的不同,你可能希望更细粒度地确定何处捕获异常以及如何捕获。

try
{
    using (var dbConn = new DbConn())
    {
        await dbConn.Connection.OpenAsync();

        command = "UPDATE user SET name = @name WHERE name IS NULL AND id = @id";

        using (MySqlCommand update = dbConn.Connection.CreateCommand())
        {
            update.CommandText = command;
            update.Parameters.Add("@name", MySqlDbType.VarChar).Value = name;
            update.Parameters.Add("@id", MySqlDbType.VarChar).Value = id;
            await update.ExecuteNonQueryAsync();
            return true;
        }
    }
}
catch (MySqlException)
{
    return false;
}

3

由于您已经在上面使用了return true,所以代码无法到达。

请使用try catch

try
            {
                using (var dbConn = new DbConn())
                {
                    await dbConn.Connection.OpenAsync();

                    command = "UPDATE user SET name = @name WHERE name IS NULL AND id = @id";

                    using (MySqlCommand update = dbConn.Connection.CreateCommand())
                    {
                        update.CommandText = command;
                        update.Parameters.Add("@name", MySqlDbType.VarChar).Value = name;
                        update.Parameters.Add("@id", MySqlDbType.VarChar).Value = id;
                        await update.ExecuteNonQueryAsync();
                        return true;
                    }
                }
            }
            catch (Exception er)
            {
                return false;
            }

1

它将进入finally块,但在finally完成后仍会抛出异常,因此在这种情况下无法返回值。


0

这是因为如果在 using 块中有异常,它会先自我处理,然后才到达 catch 块,导致你的 return false; 无法到达。我的建议是将值存储在一个变量中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接