【问题标题】:Why is this code outside my "using" statement unreachable?为什么我的“使用”语句之外的代码无法访问?
【发布时间】:2019-02-19 05:16:12
【问题描述】:

如果在 using 语句中抛出异常,它应该立即调用 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 块。
  • using 真的是 try finally 块,不是吗?

标签: c#


【解决方案1】:

确实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 块也是如此。


现在,您最可能想要做的是catch 发生的异常。快速而肮脏的方法是将所有内容包装在 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;
}

【讨论】:

    【解决方案2】:

    代码无法访问,因为您在上面已有 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;
                }
    

    【讨论】:

      【解决方案3】:

      真的很简单……

      总是

      返回
      return true;
      

      它永远没有机会到达

      return false;
      

      这是编译器最清楚的情况

      更新

      你确定吗?所以如果在 using 语句中出现异常,之前 return true 它仍然会返回 true?

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

      【讨论】:

      • 你确定吗?所以如果using语句发生异常,在return true之前还是会返回true?
      • @Bureto 不,它只会崩溃,因为您的异常将未处理。
      【解决方案4】:

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

      【讨论】:

        【解决方案5】:

        它显示是因为如果使用块出现异常,它会首先处理自己,然后它会捕获块并且您的return false; 变得无法访问。我建议将值保存在变量中。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-10-06
          • 2019-12-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多