我应该使用多少个using语句?有限制吗?

3
我注意到打开和关闭数据库连接的正确方法是使用using语句,因为它自动使用IDisposable接口释放资源(如果我有误请纠正)。
因此,我决定使用它,但在3个嵌套使用后,代码看起来有点奇怪。
这是我正在编写的一些代码,它是一个按钮的事件处理程序,我在其中使用using语句创建一些需要在使用完成后被处理的MySQL相关实例。您能告诉我是否使用得正确吗?谢谢!
private void buttonAdicionar_Click(object sender, EventArgs e)
{
    using (MySqlConnection con = new MySqlConnection(Properties.Settings.Default.ConnectionString))
    {
        using (MySqlDataAdapter da = new MySqlDataAdapter())
        {
            using (DataTable dt = new DataTable())
            {
                try
                {
                    using (MySqlCommand cmd = new MySqlCommand("SELECT codigo, descricao, unidMedida, vlUnitario FROM tab_estoque WHERE codBar = @codBar;", con))
                    {
                        cmd.Parameters.Add("@codBar", MySqlDbType.VarChar).Value = this.textBoxCodBarras.Text;

                        con.Open();
                        da.SelectCommand = cmd;
                        da.SelectCommand.ExecuteNonQuery();
                        da.Fill(dt);

                        // Caso haja alguma linha no DataSet ds então existe um produto com o codigo de barra procurado no banco de dados
                        if (dt.Rows.Count == 1)
                        {
                            bool itemIgual = false;
                            int rowIndex = 0;

                            // Passa por todas as linhas do carrinho de compras para verificar se existe outro item igual
                            foreach (DataGridViewRow dgvCarrinhoRow in dataGridViewCarrinho.Rows)
                            {
                                // Verifica se o produto da linha do carrinho de compra é o mesmo do código de barras
                                if (dgvCarrinhoRow.Cells[1].FormattedValue.ToString() == dt.Rows[0][0].ToString())
                                {
                                    // Verifica se estão tentando vender uma certa quantidade de um produto que esteja acima da quantidade do mesmo no estoque
                                    if (this.VerificarSeExcede(Convert.ToInt32(dgvCarrinhoRow.Cells[1].FormattedValue), Convert.ToInt32(dgvCarrinhoRow.Cells[3].FormattedValue) + 1) == 1)
                                    {
                                        // Adiciona mais um na quantidade do item no carrinho de compra
                                        dgvCarrinhoRow.Cells[3].Value = Convert.ToInt32(dgvCarrinhoRow.Cells[3].FormattedValue) + 1;
                                        // Multiplica o VL. ITEM. pela nova quantidade e armazena o resultado em VL. ITEM
                                        dgvCarrinhoRow.Cells[6].Value = String.Format("{0:f}",
                                            (Convert.ToDouble(dgvCarrinhoRow.Cells[3].Value) * Convert.ToDouble(dgvCarrinhoRow.Cells[5].Value)));

                                        // Adiciona o valor do produto ao valor total da venda
                                        this.totalVenda += Convert.ToDouble(dgvCarrinhoRow.Cells[5].Value);
                                    }
                                    else if (this.VerificarSeExcede(Convert.ToInt32(dt.Rows[0][0].ToString()), 1) == 0)
                                    {
                                        MessageBox.Show("Ocorreu a tentativa de vender um produto que está em falta no estoque.", "Caixa", MessageBoxButtons.OK, MessageBoxIcon.Error);
                                    }
                                    else
                                    {
                                        MessageBox.Show("Ocorreu a tentativa de vender uma certa quantidade deste produto que excede a quantidade do mesmo no estoque.", "Caixa", MessageBoxButtons.OK, MessageBoxIcon.Error);
                                    }

                                    itemIgual = true; // Evita que o if abaixo seja executado
                                    break; // Sai do loop para econimizar tempo no processamento
                                }

                                rowIndex++;
                            }

                            // Caso o item não seja igual a nenhum outro no carrinho ele é adicionado
                            if (!itemIgual)
                            {
                                // Verifica se estão tentando vender uma certa quantidade de um produto que esteja acima da quantidade do mesmo no estoque
                                if (this.VerificarSeExcede(Convert.ToInt32(dt.Rows[0][0].ToString()), 1) == 1)
                                {
                                    this.dataGridViewCarrinho.Rows.Add(
                                        ++this.item,                     // ITEM
                                        dt.Rows[0][0],    // CÓDIGO
                                        dt.Rows[0][3],    // DESCRIÇÃO
                                        1,                          // QTD.
                                        dt.Rows[0][2],    // UN.
                                        dt.Rows[0][3],    // VL. UNIT.
                                        dt.Rows[0][3]);   // VL. ITEM.

                                    // Adiciona o valor do produto ao valor total da venda
                                    this.totalVenda += Convert.ToDouble(dt.Rows[0][3].ToString());
                                }
                                else if (this.VerificarSeExcede(Convert.ToInt32(dt.Rows[0][0].ToString()), 1) == 0)
                                {
                                    MessageBox.Show("Ocorreu a tentativa de vender um produto que está em falta no estoque.", "Caixa", MessageBoxButtons.OK, MessageBoxIcon.Error);
                                }
                                else
                                {
                                    MessageBox.Show("Ocorreu a tentativa de vender uma certa quantidade deste produto que excede a quantidade do mesmo no estoque.", "Caixa", MessageBoxButtons.OK, MessageBoxIcon.Error);
                                }
                            }

                            this.AtualizarValorCompra();
                            this.dataGridViewCarrinho.ClearSelection();
                        }
                        else // Mensagem exibida caso a consulta nao retorne alguma coisa
                        {
                            MessageBox.Show("Este item não consta no banco de dados.", "Caixa", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        }
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Ocorreu um erro durante a comunicação com o banco de dados.\n\n" + ex.Message, "Caixa", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }
    }

    this.LimparControles(1);
}
2个回答

8

嵌套层数没有固定限制,无论是否使用using关键字,但是在屏幕上显示过多的嵌套会让眼睛感到不适。因此,通常建议限制嵌套层数。你可以通过观察复合语句后面的花括号是可选的来实现这一点。因此,你可以这样做:

using (MySqlConnection con = new MySqlConnection(Properties.Settings.Default.ConnectionString))
using (MySqlDataAdapter da = new MySqlDataAdapter())
using (DataTable dt = new DataTable()) {
    ...
}

这些语句仍然像以前一样嵌套在彼此的内部,但在屏幕上看起来"扁平化"。

这种方法的一个限制是所有三个变量(condadt)都将在相同作用域的末尾被释放。在这种特定情况下,这不是一个问题,因为您在结束所有三个作用域时没有任何语句(即,在末尾有三个闭括号)。然而,如果需要提前结束其中一个变量的作用域,可能会迫使您使用额外的嵌套级别。


谢谢你提供的信息,我之前不知道我可以这样做! - Zignd

2
我倾向于将它们堆叠起来,就像这样:

try
{
    using (var connection = new MySqlConnection(...))
    using (var adapter = new MySqlDataAdapter())
    using (var table = new DataTable())
    using (var cmd = new MySqlCommand(...))
    {
        ...
    }
}

需要注意的是,如果作用域只有一条指令,那么它不需要被大括号 { } 包围。
对于 foreachif 块也是同样适用。
foreach(var x in y) DoSomething();

感谢您提供的信息,retailcoder。但是,dasblinkenlight的回答看起来更加完整。 - Zignd
没问题,我编辑了一下并加入了更多的内容;这个想法是,如果作用域只有一个指令,那么它就不需要大括号。 - Mathieu Guindon
@Zignd 实际上你应该接受dasblinkenlight的答案,它不仅更完整,而且还告诉你为什么/何时应该引入缩进级别;我的回答只是告诉你为什么不需要缩进级别。 - Mathieu Guindon

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