C# 如果没有大括号,using语句有什么作用域
我继承了以下代码:C# 如果没有大括号,using语句有什么作用域,c#,ado.net,using-statement,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
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();
}
查看代码,我在using子句之后扩展了一个大括号
代码编译并执行预期的操作。应用程序的行为不可预测。有时它无法访问数据库服务器
这个代码有意义吗?dataAccessConnection是否具有rigth作用域?
使用不带显式大括号的
语句仅适用于以下语句
using (Idisp1)
// use it
// it's disposed
using (Idisp1)
using (Idisp2)
{
}
因此,当使用链条时,它们的工作方式相同。第二个在这里用作一条语句
using (Idisp1)
// use it
// it's disposed
using (Idisp1)
using (Idisp2)
{
}
Commenter stakx建议使用格式化来明确编译器如何使用块读取数据。实际上,这些文件通常会被格式化为遇到的OP:
using (Idisp1)
using (Idisp2)
{
}
这相当于:
using (Idisp1)
{
using (Idisp2)
{
}
}
请注意,顶部的第一个始终是要处理的最后一个。因此,在前面的所有示例中,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
}
我们获取响应,获取流,获取读取器,读取流,处理读取器,处理流,最后处理响应
请注意,正如评论员Nikhil Agrawal所指出的,这是一种关于块的语言特性,它不特定于使用
关键字的。例如,如果
块:
if (condition)
// may or may not execute
// definitely will execute
对
if (condition1)
if (condition2)
// will execute if both are true
// definitely will execute
当然,尽管你永远不应该这样使用if
语句,因为读起来很糟糕,但我认为这有助于你理解使用
的情况。我个人非常喜欢使用块链接。C语言规范()将使用
语句的描述为:
使用语句:
使用(
资源获取)
嵌入式语句
即:
using
语句获取一个或多个资源,执行语句,然后处置资源
(我的重点)
那么,我们最终如何将其与花括号一起使用呢?因为嵌入式语句的定义是:
嵌入语句:
块
空语句
表达式语句
选择语句
迭代语句
跳转语句
try语句
选中的语句
未选中的语句
锁定语句
使用语句
收益率报表
以及:
嵌入语句nonterminal用于出现在其他语句中的语句
最后,我们发现块的定义如下:
块允许在允许单个语句的上下文中编写多个语句
区块:
{
语句列表opt}
所以基本上,花括号总是可以用来表示一条语句被接受的情况,而不是有多条语句
碰巧的是,我们几乎总是希望使用多个语句,因此大括号往往被视为if
,using
等语句的一部分。然而,事实上,它们是语言的一个独立部分。从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();
}
}
输出
Using 1
No Using 2
Using 3
No Using 4
Using 3 disposed
Using 1 disposed
使用1
禁止使用2
使用3
禁止使用4
使用3
使用1
该链接上的一位评论员说,“看起来第一个using语句是空的,没有使用过。”。这就是发生在我身上的事。但我现在明白了,它实际上是一种干净的风格,“使用”就像“如果”一样有效。即使我个人使用大括号,如果一个元素更准确地跟随,它也可以不使用大括号,我会说它们适用于以下语句(正如你所观察到的,它实际上可能会跨越多行)@Damien_,不信者对!这就是我要找的词。我将编辑我的答案。谢谢。@MatthewHaugen:您可以添加:此块行为是用语言实现的,不是特定于使用的。@MatthewHaugen-自C#8.0以来,情况发生了变化,对吗?@Homer是和否-情况确实得到了添加,但我在这里说的仍然是真的。“简单使用语句”没有paren。因此使用(var resp=req.GetResponse())
仍然只保留下一行的作用域,但是使用var resp=req.GetResponse()
将一直持续到块的末尾。下次有机会我会编辑的。所以,也许我遗漏了什么,但这有什么意义呢?在函数/方法中声明变量和使用此方法是否会产生相同的结果?我认为将静态Main
方法移到类Disposable
之外会使示例更容易理解。