据我所知,每当我实例化一个实现IDisposable的类时,我都应该使用using
关键字,以确保它被正确处理。
像这样:
using (SecureString s = new SecureString())
{
}
以上内容对我来说很容易理解 - 我可以使用s
但我希望在这些括号内,但是一旦我离开这些括号,我就不能再引用s
了。范围很容易看到。
但我不明白的是当你使用using
没有括号时它是如何工作的。
private void Function()
{
// Some code here
using (SecureString s = new SecureString())
// more code here
}
你根本不需要使用括号......所以...如果没有括号可以使用{{1,我怎么知道我能够在哪里使用该对象以及它在何处被处置关键字?
答案 0 :(得分:8)
在C#中几乎每种情况下,当你可以选择使用大括号时,你可以用一行代码替换它们。
考虑if语句:
if (someBool)
DoSomething();
else
DoSomethingElse();
这与以下内容一样有效:
if (someBool)
{
// do lots of things
}
else
DoSomethingElse();
这可能几乎普遍适用于您可以使用{
和}
括号的任何时间。
使用using
语句的好处是你可以像这样嵌套它们:
using (var stream = new NetworkStream(...))
using (var sslStream = new SslStream(stream))
using (var reader = new StreamReader(sslStream))
{
reader.WriteLine(...);
}
这相当于以下内容:
using (var stream = new NetworkStream(...))
{
using (var sslStream = new SslStream(stream))
{
using (var reader = new StreamReader(sslStream))
{
reader.WriteLine(...);
}
}
}
虽然我认为你同意它看起来更好看。
答案 1 :(得分:6)
没有大括号的using
表示using
仅在 的下一个语句的范围内 - 与if
条件的工作方式相同。
using (SecureString s = new SecureString())
s.Foo(); // Works
s.Foo(); // out of scope
作为个人偏好,我总是包括大括号,即使是单个语句if
/ using
构造,也可以避免混淆这样的情况。
答案 2 :(得分:3)
然后它仅在using语句之后的下一个命令中有效。
请注意,这并不意味着下一行。只有下一个命令。
答案 3 :(得分:2)
范围基本上限于下一行。
using(var s = new SecureString())
s.Whatever();
s.Whatever() // ERROR! s is out of scope
与使用不带括号的if
关键字相同:
if(x == y)
x = 4;
答案 4 :(得分:2)
使用using
,if
和foreach
等语句,如果不包含括号,则范围只是下一个语句(通常是下一行)。它就像你在下一个声明中包括括号一样对待。 E.g。
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
答案 5 :(得分:2)
正如大家都回答的那样,你基本上可以使用与此相同的内联使用语句:
using(var s = new SecureString()) s.Whatever();
但请不要这样做,因为在我看来,你会使代码的可读性降低,并使其他开发人员感到困惑。我认为这一点很好地说明了你提出这个问题。
答案 6 :(得分:1)
扩展其他答案:
using (SecureString s = new SecureString())
// This statement is in using scope.
// This is not.
答案 7 :(得分:1)
如果您不使用括号,则只有下一个语句有效
using (SecureString s = new SecureString())
// statement here
如果要包含多个语句,请使用括号。
答案 8 :(得分:1)
如果没有括号,你只需要一行。与“if”或“for”语句相同。 例如:
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");
答案 9 :(得分:0)
using
,就像for
,while
,if
,else
以及许多其他关键字一样,只需要一个语句作为“正文” “块。
如果程序员想要在正文中执行多个语句,他们可以使用花括号来创建复杂语句,即执行多个(或零)语句的单个语句。当您在using
或if
之后使用花括号时,“此处的所有内容都应视为一个语句”。如果您已经开始使用完全一个语句,则无需使用大括号将其转换为单个语句,因此您可以省略它们。
答案 10 :(得分:0)
查看反汇编会准确显示正在发生的事情。
static private void Function()
{
Console.WriteLine("before");
using (SecureString s = new SecureString())
s.Clear();
Console.WriteLine("after");
}
使用 IL Dissassembler ,上面的函数反汇编到下面的代码。您可以看到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
答案 11 :(得分:0)
正如在其他评论中提到的,当按照你提到的方式使用 using 语句时,只有当你有一行时。
我想在 C# 8.0
中添加,您可以这样使用 "using declarations":
private void Function()
{
// Some code here
using SecureString s = new SecureString();
// more code here
}
这样,using
语句的生命周期将延伸到声明它的作用域的末尾。然后,using
局部变量将按照与声明它们的相反顺序进行处理。