C#和#x27 ;;s使用关键字
我知道,每当我实例化一个实现IDisposable的类时,我都应该使用C#和#x27 ;;s使用关键字,c#,using-statement,C#,Using Statement,我知道,每当我实例化一个实现IDisposable的类时,我都应该使用using关键字,以确保正确地处理它 像这样: using (SecureString s = new SecureString()) { } 以上内容对我来说很容易理解-我可以使用s,但是我想在这些括号内使用,但是一旦我离开这些括号,我就不能再引用s。这个范围很容易看到 但我不明白的是,当你使用没有括号的时,它是如何工作的 private void Function() { // Some code here
using
关键字,以确保正确地处理它
像这样:
using (SecureString s = new SecureString())
{
}
以上内容对我来说很容易理解-我可以使用s
,但是我想在这些括号内使用,但是一旦我离开这些括号,我就不能再引用s
。这个范围很容易看到
但我不明白的是,当你使用没有括号的时,它是如何工作的
private void Function()
{
// Some code here
using (SecureString s = new SecureString())
// more code here
}
您根本不需要使用括号。。。所以我如何知道在哪里可以使用该对象以及在哪里处置该对象,如果没有括号与using
关键字一起使用?则它仅在using语句后的下一个命令中有效
请注意,这并不意味着下一行。只有下一个命令。在C语言中,几乎所有情况下,当您可以选择使用大括号时,您可以用一行代码替换它们
考虑一个if语句:
if (someBool)
DoSomething();
else
DoSomethingElse();
这与以下内容一样有效:
if (someBool)
{
// do lots of things
}
else
DoSomethingElse();
using (var stream = new NetworkStream(...))
{
using (var sslStream = new SslStream(stream))
{
using (var reader = new StreamReader(sslStream))
{
reader.WriteLine(...);
}
}
}
这可能在任何时候都是普遍适用的,您可以使用{
和}
括号
private void Function()
{
// Some code here
using (SecureString s = new SecureString())
// more code here
}
使用using
语句的好处在于,您可以像这样嵌套它们:
using (var stream = new NetworkStream(...))
using (var sslStream = new SslStream(stream))
using (var reader = new StreamReader(sslStream))
{
reader.WriteLine(...);
}
这相当于以下内容:
if (someBool)
{
// do lots of things
}
else
DoSomethingElse();
using (var stream = new NetworkStream(...))
{
using (var sslStream = new SslStream(stream))
{
using (var reader = new StreamReader(sslStream))
{
reader.WriteLine(...);
}
}
}
尽管我想你会同意它看起来漂亮多了。要扩展其他答案:
using (SecureString s = new SecureString())
// This statement is in using scope.
// This is not.
范围基本上仅限于下一行
using(var s = new SecureString())
s.Whatever();
s.Whatever() // ERROR! s is out of scope
这与使用不带括号的if
关键字相同:
if(x == y)
x = 4;
对于像using
、if
和foreach
这样的语句,如果不包括括号,范围就是下一条语句(通常是下一行)。它的处理方式就像你在下一句话的括号里一样。例如
if (someCondition)
Console.WriteLine("someCondition is true!");
Console.WriteLine("I run regardless");
// same as
if (someCondition)
{
Console.WriteLine("someCondition is true!");
}
using (var s = new SecureString())
Console.WriteLine(s); // this works!
//Console.WriteLine(s); // s is no longer in scope, this won't compile
不带大括号的使用
表示使用
仅在下一条语句的范围内-与if
条件起作用的方式相同
using (SecureString s = new SecureString())
s.Foo(); // Works
s.Foo(); // out of scope
作为个人偏好,我总是使用大括号,即使对于使用
结构的单个语句if
/,也要使用大括号,以避免类似的混乱情况。如果不使用括号,则只有下一个语句有效
using (SecureString s = new SecureString())
// statement here
如果要包含多条语句,请使用括号。如果没有括号,只需一行即可。与“if”或“for”语句相同。
private void Function()
{
// Some code here
using (SecureString s = new SecureString())
// more code here
}
例如:
for (int i = 0; i < 10; i++)
Console.WriteLine(i.ToString());
if (str == "hello")
Console.WriteLine("hello back!");
using (SecureString s = new SecureString())
Console.WriteLine("Here we have s");
Console.WriteLine("but here it's out of scope already");
for(int i=0;i<10;i++)
Console.WriteLine(i.ToString());
如果(str==“你好”)
控制台。WriteLine(“您好,回来!”);
使用(SecureString s=new SecureString())
Console.WriteLine(“这里有s”);
WriteLine(“但在这里它已经超出范围”);
因为每个人都回答了这个问题,您基本上可以有一个与此等价的内联using语句:
using(var s = new SecureString()) s.Whatever();
但是,请不要这样做,因为在我看来,这会降低代码的可读性,并使其他开发人员感到困惑。你问了这个问题,我认为这一点很好地说明了。使用
,就像for
,while
,if
,else
,以及其他许多关键字一样,总是将一条语句作为块的“主体”
如果程序员希望在主体中执行多条语句,他们可以使用大括号创建复杂语句,即执行多条(或零条)语句的单个语句。当您在之后使用大括号时,如果使用或如果使用,您的意思是,“这里的所有内容都应被视为一个语句”。如果您已经有一条语句要开始,则无需使用大括号将其转换为一条语句,因此您可以省略它们。查看反汇编将准确地显示正在进行的操作
static private void Function()
{
Console.WriteLine("before");
using (SecureString s = new SecureString())
s.Clear();
Console.WriteLine("after");
}
使用IL disassembler,上面的函数反汇编成下面的代码。您可以看到,using
语句是通过一个try finally
包装语句的其余部分来实现的(它可以是一个由大括号定义的块,但在本例中只是分号)。您正在使用的对象在finally
块中进行处理。然后,在finally
之外,代码继续执行源代码的下一条语句
.method private hidebysig static void Function() cil managed
{
// Code size 56 (0x38)
.maxstack 2
.locals init ([0] class [mscorlib]System.Security.SecureString s,
[1] bool CS$4$0000)
IL_0000: nop
IL_0001: ldstr "before"
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
IL_000b: nop
IL_000c: newobj instance void [mscorlib]System.Security.SecureString::.ctor()
IL_0011: stloc.0
.try
{
IL_0012: ldloc.0
IL_0013: callvirt instance void [mscorlib]System.Security.SecureString::Clear()
IL_0018: nop
IL_0019: leave.s IL_002b
} // end .try
finally
{
IL_001b: ldloc.0
IL_001c: ldnull
IL_001d: ceq
IL_001f: stloc.1
IL_0020: ldloc.1
IL_0021: brtrue.s IL_002a
IL_0023: ldloc.0
IL_0024: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0029: nop
IL_002a: endfinally
} // end handler
IL_002b: nop
IL_002c: ldstr "after"
IL_0031: call void [mscorlib]System.Console::WriteLine(string)
IL_0036: nop
IL_0037: ret
} // end of method Program::Function
就像没有括号的if
或for
一样。旁白:实际上,在一些边缘情况下,这样做是错误的:您可以尝试一下。通过一些简单的实验很容易弄明白…@VladimirFrolov Ohhh谢谢你。这完全有道理。我觉得现在没有意识到这一点很傻。更准确地说,这是下一句话——它可能跨越几行,甚至可能在前一行。如果该行由多个语句组成,则只有第一个语句在using
语句中。@JonSkeet您完全正确。为了清楚起见,我更新了我的答案。如果你要投反对票,至少要有智慧来评论为什么我的答案值得投反对票。否则,我如何从我的“错误”答案中学习呢?关于如何澄清代码意图的进一步思考:并不是自动添加大括号;所有这些结构的主体总是恰好是一个语句;大括号允许您将多个语句视为单个语句。如果您已经有了一个语句,那么就不需要它们了。它不像语法明确地将大括号列为可选的。这些结构简单地说,它们后面跟着一条语句,不管该语句是什么。是的,但我觉得用我的方式来描述它更有意义,因为人们通常会这样想。哇,5分钟内10-12个正确答案回答了我的问题。我不知道该选哪个答案。我现在问这么一个明显的问题感到很傻。但我选择这一个是因为你指出了正是这种情况导致了我被欺骗