如果我在使用中使用 null 进行初始化,我是否仍会获得 Dispose 优势?

Will I still get the Dispose advanges, if I in a using, initialize with null?

我想重构我的 SqlDataReader 代码,所以它使用 using..

SqlDataReader reader = null;
reader = xdCmd.ExecuteReader();
// use reader..

我可以使用解决方案 1),我在使用中声明 reader,然后先用 SqlDataReader 初始化它,并且仍然得到 Dispose "features"使用提供?或者我是否需要像解决方案 2) 中那样进行初始化,在 using 中立即进行初始化? 我猜 1) 没问题,但我不确定。

1)

using (SqlDataReader reader = null)
{
    xdCmd.CommandText = $"select * from {tableName}";
    reader = xdCmd.ExecuteReader();
    // use reader..
}

2)

using (SqlDataReader reader = new SqlDataReader(new SqlCommand($"select * from {tableName}"), xdCon))
{
    reader = xdCmd.ExecuteReader();
    // use reader..
}

对我来说,我更喜欢使用第二种解决方案,它更微妙,或者您可以使用我下面的示例:

using (var sqlConnection = new SqlConnection(connection))
{
       using (var command = new SqlCommand(query, sqlConnection))
       {
            using (var read = command.ExecuteReader())
            {
                // process on your read
            }
       }
}

C# 语言不包含表达对象概念的语法 "ownership" 或与 Rust 不同的生命周期管理,因此完全取决于 API 的文档来说明对象的构造函数是否采用是否拥有其参数(以及谁可以调用 .Dispose())。这不是 C# 编译器可以为您确定的事情。然而 .Dispose() 实现无论如何都必须是幂等的 所以调用 .Dispose() 多次(冗余)没有坏处。

只需遵循堆栈 using 语句的 C# 惯用约定:

using( SqlConnection c = new SqlConnection( connectionString ) )
using( SqlCommand cmd = c.CreateCommand() )
{
    await c.OpenAsync().ConfigureAwait(false);

    cmd.CommandText = "SELECT foo, bar FROM baz";

    using( SqlDataReader rdr = await cmd.ExecuteReaderAsync().ConfigureAwait(false) )
    {
        ...
    }
}