如果没有花括号,using语句的范围是什么

Mat*_*s F 7 c# ado.net using-statement

我继承了以下代码:

    using (var dataAccessConnection = da.GetConnection()) //no opening curly brace here
    using (var command = new SqlCommand(sql, dataAccessConnection.Connection))
    {
        command.CommandType = CommandType.Text;
        using (var sqlDataReader = command.ExecuteReader(CommandBehavior.CloseConnection))
        {
            while (sqlDataReader.Read())
            {
                rueckgabe.Add(new Myclass
                                  {
                                      Uid = Guid.NewGuid(),
                                      ImportVersionUid = versionUid,
                                      MyProperty = Convert.ToInt32(sqlDataReader["MyProperty"])
                                        });       
            }
        }
        command.Connection.Close();
        dataAccessConnection.Connection.Close();
    }
Run Code Online (Sandbox Code Playgroud)

看一下代码,我在使用子句之后开了一个大括号.

代码编译并执行预期的操作.该应用程序的行为不可预测.有时它无法访问数据库服务器.

这段代码有意义吗?dataAccessConnection是否具有严格的范围?

Gop*_*ddy 29

从 C# 8.0 开始,该using关键字可以用作一次性对象(参考)的变量声明中的属性。语义如您所料——对象在范围的末尾自动处理。

        public class Disposable : IDisposable
        {
            string name;

            public Disposable(string name)
            {
                this.name = name;
            }

            public void Dispose()
            {
                Console.WriteLine(name + " disposed");
            }

            public void Identify()
            {
                Console.WriteLine(name);
            }

            static void Main(string[] args)
            {
                using Disposable d1 = new Disposable("Using 1");
                Disposable d2 = new Disposable("No Using 2");
                using Disposable d3 = new Disposable("Using 3");
                Disposable d4 = new Disposable("No Using 4");
                d1.Identify();
                d2.Identify();
                d3.Identify();
                d4.Identify();
            }
        }
Run Code Online (Sandbox Code Playgroud)

输出

使用 1
不使用 2
使用 3
不使用 4
使用 3 处理
使用 1 个处置

  • 这是很好的信息,但是 2014 年的问题没有使用 C# 8 功能!注意“using”后面是否有“( ... )”。例如,语句 `using Disposable d1 = new Disposable("Using 1");` 就像您的示例中一样,声明了 `d1` 变量,该变量在方法的其余部分(或我们所在的任何块)的范围内,并且当控制离开时将被处置。相比之下,“using (Disposable d1 = new Disposable("Using 1"));”是旧式语法,其中变量“d1”的范围只是最后看到的空语句“;”!这里的“;”就像“{}”。 (7认同)
  • 那么,也许我错过了一些东西,但这有什么意义呢?在函数/方法中声明变量和使用此方法不会有相同的结果吗? (6认同)
  • 因此,虽然此答案中的信息可能是人们今天通常寻找的信息,但_原始_ 2014 年问题的解决方案是在此处的其他答案中看到的。第一个“using”语句的范围是紧随其后的(嵌入的)“using”语句。 (6认同)
  • 我认为将静态“Main”方法移到“Disposable”类之外将使该示例更容易理解。 (3认同)

Mat*_*gen 12

using 没有显式花括号的语句仅适用于以下语句.

using (Idisp1)
    // use it

// it's disposed
Run Code Online (Sandbox Code Playgroud)

因此,当链接时,它们以相同的方式工作.第二个using在此作为单一陈述.

using (Idisp1)
    using (Idisp2)
    {

    }
Run Code Online (Sandbox Code Playgroud)

Commenter stakx建议格式化以明确编译器如何读取使用块.实际上,这些通常会被视为OP遇到的格式:

using (Idisp1)
using (Idisp2)
{

}
Run Code Online (Sandbox Code Playgroud)

这相当于:

using (Idisp1)
{
    using (Idisp2)
    {

    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,顶部的第一个始终是最后一个处置.因此,在之前的所有示例中,Idisp2.Dispose()之前都会调用Idisp1.Dispose().在许多情况下,你会做这样的事情并不重要,但我相信你应该始终了解你的代码会做什么,并做出明智的决定而不关心.

这方面的一个例子是在阅读网页时:

HttpWebRequest req = ...;

using (var resp = req.GetResponse())
using (var stream = resp.GetResponseStream())
using (var reader = new StreamReader(stream))
{
    TextBox1.Text = reader.ReadToEnd(); // or whatever
}
Run Code Online (Sandbox Code Playgroud)

我们得到响应,获取流,获取读者,读取流,处理读取器,处理流,最后,处理响应.

请注意,正如评论者Nikhil Agrawal指出的那样,这是一种关于非using关键字特定的块的语言功能.例如,同样适用于if块:

if (condition)
    // may or may not execute

// definitely will execute
Run Code Online (Sandbox Code Playgroud)

if (condition1)
    if (condition2)
       // will execute if both are true

// definitely will execute
Run Code Online (Sandbox Code Playgroud)

当然,你不应该以if这种方式使用语句,因为阅读起来很可怕,但我认为这有助于你理解这个using案例.我个人对链接using块非常好.

  • @Homer是的,也不是——事情肯定已经添加了,但我在这里所说的仍然是正确的。“简单的 using 语句”没有括号。因此,“using (var resp = req.GetResponse())”仍然只保留下一行的范围,但“using var resp = req.GetResponse()”将一直保留到块的末尾。下次有机会我会编辑的。 (3认同)
  • 更确切地说,我会说它们适用于以下语句(正如您所观察到的,实际上可能会在多行上运行) (2认同)
  • @MatthewHaugen - 自 C# 8.0 以来事情已经发生了变化,对吧? (2认同)