C#IDisposable使用:最佳实践

C#IDisposable使用:最佳实践,c#,coding-style,idisposable,using,C#,Coding Style,Idisposable,Using,我已经在USING语句中包装了我的OracleConnection和OracleCommand对象一段时间了,但是,在运行代码分析器之后,我发现OracleParameter还实现了IDisposable。以下代码正确吗?是否有更好的可读性或结构技术?乍一看,它似乎被使用语句弄得乱七八糟: using (OracleConnection conn = new OracleConnection(connectionstring)) { conn.Open(); using (Ora

我已经在USING语句中包装了我的OracleConnection和OracleCommand对象一段时间了,但是,在运行代码分析器之后,我发现OracleParameter还实现了IDisposable。以下代码正确吗?是否有更好的可读性或结构技术?乍一看,它似乎被使用语句弄得乱七八糟:

using (OracleConnection conn = new OracleConnection(connectionstring))
{
    conn.Open();
    using (OracleCommand cmd = new OracleCommand(sql, conn))
    {
        cmd.BindByName = true;

        using (OracleParameter param1 = new OracleParameter("p1", OracleDbType.Int32, System.Data.ParameterDirection.Input))
        {
            param1.Value = int.Parse(value1);
            cmd.Parameters.Add(param1);
        }

        using (OracleParameter param2 = new OracleParameter("p2", OracleDbType.Varchar2, System.Data.ParameterDirection.Input))
        {
            param2.Value = value2;
            cmd.Parameters.Add(param2);
        }

        using (OracleDataReader dr = cmd.ExecuteReader())
        {
            // loop data here...
        }
    }
}

我不确定那是否能正常工作。考虑到在使用结束时,两个参数都应该被处理。您的
cmd.Parameters
对象仍保留对它们的引用这一事实并不排除在
OracleParameter
Dispose方法中可能发生的情况。出于所有密集目的,该特定对象的开发人员可能正在清除您的
OracleCommand
希望填充的字段

那里有些危险。如果您完全确定要正确处理
OracleParameters
,我建议您在使用
OracleDataReader
后处理它们


请记住,通常在使用完对象后调用
Dispose
。你告诉它释放它保留在池中的所有资源。如果您没有使用完对象,不要过早地处理它。

否这是不正确的,因为您甚至在使用参数之前就处理了参数

相反,你应该这样做

OracleParameter param1 = new OracleParameter("p1", OracleDbType.Int32, System.Data.ParameterDirection.Input);

param1.Value = int.Parse(value1);
cmd.Parameters.Add(param1);


OracleParameter param2 = new OracleParameter("p2", OracleDbType.Varchar2, System.Data.ParameterDirection.Input);

param2.Value = value2;
cmd.Parameters.Add(param2);


using (OracleDataReader dr = cmd.ExecuteReader())
{
  // loop data here...
}

param1.dispose();
param2.dispose();

你能看一下连接和命令的源代码吗?它是否处理了参数?如果连接或命令对象释放模式包装参数,并在释放后进行释放。你应该担心。我认为这是/应该的。

您希望仅在参数使用结束时,包括在查询期间(以及可能在读取结果时),才处理这些参数:

请注意,您可以使用语句将多个
放在一行中。这是因为,就像
if
语句一样

  • 使用
  • 语句的
    被认为是一个简单语句(即使有块);及
    
  • 使用
  • 语句的
    可以包含块或下面的语句
    
    此代码不正确。您创建的参数仍然在
    using
    语句作用域之外使用,因为您将它们添加到参数集合中,但是
    using
    语句将在控件离开作用域时对参数调用
    Dispose
    。这意味着,当使用命令中的参数时,您只需使用
    连接
    数据读取器
    对象。我从未见过使用ADO.NET参数对象的
    (或
    .Dispose()
    )。如果这是必要的,甚至是可取的,我认为它在过去10年中已经出现了。

    MSDN正在讨论BCL提供的对象。Oracle实现这些功能很可能需要处理这些参数。如果不打算处置它们,它们为什么要实现IDisposable?或者它们很可能不会。我从未见过任何ADO.NET代码(用于Oracle的实现或其他任何人的实现)对参数对象调用Dispose(),或使用
    块将其放入
    。同样,如果需要处理参数,这在很久以前就已经出现了。因此,您的建议是,即使对象实现了IDisposble,除非已知有问题,否则不要处理它?对我来说,这听起来是个糟糕的建议。我可以很容易地选择比“抱歉”更好的安全路线并进行处置,但我真的认为Oracle搞砸了这一点,他们的处置方法可能没有任何意义。虽然有许多类似的答案,但我感谢您提供了示例和注释。谢谢!很高兴我能帮上忙。:-)
    
    using (OracleConnection conn = new OracleConnection(connectionstring)) 
    using (OracleCommand cmd = new OracleCommand(sql, conn)) 
    using (OracleParameter param1 = new OracleParameter("p1", OracleDbType.Int32,
           System.Data.ParameterDirection.Input)) 
    using (OracleParameter param2 = new OracleParameter("p2", OracleDbType.Varchar2,
           System.Data.ParameterDirection.Input)) 
    }
        conn.Open(); 
        cmd.BindByName = true; 
    
        param1.Value = int.Parse(value1); 
        cmd.Parameters.Add(param1); 
    
        param2.Value = value2; 
        cmd.Parameters.Add(param2); 
    
        using (OracleDataReader dr = cmd.ExecuteReader()) 
        { 
            // loop data here... 
        } 
    } 
    
    using (OracleConnection conn = new OracleConnection(connectionstring))
    {
        conn.Open();
        using (OracleCommand cmd = new OracleCommand(sql, conn))
        {
            cmd.BindByName = true;
    
            using (OracleParameter param1 = new OracleParameter("p1", OracleDbType.Int32, System.Data.ParameterDirection.Input))
            using (OracleParameter param2 = new OracleParameter("p2", OracleDbType.Varchar2, System.Data.ParameterDirection.Input))
            {
                param1.Value = int.Parse(value1);
                cmd.Parameters.Add(param1);
                param2.Value = value2;
                cmd.Parameters.Add(param2);
    
                using (OracleDataReader dr = cmd.ExecuteReader())
                {
                    // loop data here...
                }
            }
        }
    }