using
语句的原因是确保对象在超出范围时立即被处理,而不需要显式代码来确保发生这种情况。
就像在理解C#中的'using'语句(codeproject)和使用实现IDisposable的对象(microsoft)中一样,C#编译器会转换
using (MyResource myRes = new MyResource())
{
myRes.DoSomething();
}
到
{ // Limits scope of myRes
MyResource myRes= new MyResource();
try
{
myRes.DoSomething();
}
finally
{
// Check for a null resource.
if (myRes != null)
// Call the object's Dispose method.
((IDisposable)myRes).Dispose();
}
}
using var myRes = new MyResource();
myRes.DoSomething();
当控制权离开包含范围(通常是一个方法,但也可以是代码块)时,myRes
将被处理。
using
语句可以确保在使用完对象后调用 Dispose
方法。 - John SaundersMyRessource
是一个结构体时,生成的代码会有所不同。显然没有对空值进行测试,也没有装箱到IDisposable
。将发出一个受限制的虚拟调用。 - Romain Verdierusing
,则在其内部构建的变量是只读的。没有办法在没有 using
语句的情况下对局部变量实现这一点。 - Massimiliano Krauswith open(filename) as f: # blah
的东西? - Chromium由于仍有很多人这样做:
using (System.IO.StreamReader r = new System.IO.StreamReader(""))
using (System.IO.StreamReader r2 = new System.IO.StreamReader("")) {
//code
}
我猜很多人还不知道你可以这样做:
using (System.IO.StreamReader r = new System.IO.StreamReader(""), r2 = new System.IO.StreamReader("")) {
//code
}
这样的事情:
using (var conn = new SqlConnection("connection string"))
{
conn.Open();
// Execute SQL statement here on the connection you created
}
即使出现异常,也无需使用try
/catch
/finally
块,此SqlConnection
将在不需要显式调用.Close()
函数的情况下关闭。
using
块的中间return
,连接仍然会被关闭。 - Joel Coehoornusing可以用来调用IDisposable。它还可以用于给类型起别名。
using (SqlConnection cnn = new SqlConnection()) { /* Code */}
using f1 = System.Windows.Forms.Form;
using,在技术语境下指
using (var foo = new Bar())
{
Baz();
}
实际上是try/finally块的简写。它等同于以下代码:
var foo = new Bar();
try
{
Baz();
}
finally
{
foo.Dispose();
}
当然,您会注意到第一个代码片段比第二个更加简洁,并且即使抛出异常,您可能仍然想要进行许多种清理操作。因此,我们提出了一种称为Scope的类,它允许您在Dispose方法中执行任意代码。例如,如果您有一个名为IsWorking的属性,在尝试执行操作后始终希望将其设置为false,您可以这样做:
using (new Scope(() => IsWorking = false))
{
IsWorking = true;
MundaneYetDangerousWork();
}
您可以在这里了解我们的解决方案及其来源。
Microsoft文档说明using具有双重功能(https://msdn.microsoft.com/zh-cn/library/zhdeatwt.aspx),既可作为指令,也可用于语句。作为语句,正如其他答案中所指出的那样,该关键字基本上是一种语法糖,用于确定处置IDisposable对象的范围。作为指令,它通常用于导入命名空间和类型。同时作为指令,你可以为命名空间和类型创建别名,就像Joseph和Ben Albahari在书籍《C# 5.0 In a Nutshell: The Definitive Guide》(http://www.amazon.com/5-0-Nutshell-The-Definitive-Reference-ebook/dp/B008E6I1K8)中所指出的那样。以下是一个例子:
namespace HelloWorld
{
using AppFunc = Func<IDictionary<DateTime, string>, List<string>>;
public class Startup
{
public static AppFunc OrderEvents()
{
AppFunc appFunc = (IDictionary<DateTime, string> events) =>
{
if ((events != null) && (events.Count > 0))
{
List<string> result = events.OrderBy(ev => ev.Key)
.Select(ev => ev.Value)
.ToList();
return result;
}
throw new ArgumentException("Event dictionary is null or empty.");
};
return appFunc;
}
}
}
这是需要明智采纳的做法,因为滥用这种做法可能会损害代码的清晰度。在DotNetPearls有一个很好的C#别名解释,还提到了其优缺点(http://www.dotnetperls.com/using-alias)。
using
作为别名工具。当阅读代码时,它会让我感到困惑-- 我已经知道System.Collections
存在并且有IEnumerable<T>
类。使用别名将其命名为其他名称会使其对我变得模糊不清。例如,我看到using FooCollection = IEnumerable<Foo>
可能会让后来的开发人员阅读代码时想,“什么是FooCollection
,为什么没有相应的类?”我从不使用它,并且会劝阻其使用。但这可能只是我的个人观点。 - Ari Roth我过去常常使用它来处理输入输出流。你可以很好地嵌套它们,并且它消除了通常会遇到的许多潜在问题(通过自动调用dispose)。例如:
using (FileStream fs = new FileStream("c:\file.txt", FileMode.Open))
{
using (BufferedStream bs = new BufferedStream(fs))
{
using (System.IO.StreamReader sr = new StreamReader(bs))
{
string output = sr.ReadToEnd();
}
}
}
我想补充一点,我很惊讶这个问题没有被提到。在我看来,使用语句最有意思的功能是无论你如何退出使用块,它都会自动释放对象,包括返回和异常。
using (var db = new DbContext())
{
if(db.State == State.Closed)
throw new Exception("Database connection is closed.");
return db.Something.ToList();
}
使用 using 的另一个伟大用途是在实例化模态对话框时。
Using frm as new Form1
Form1.ShowDialog
' Do stuff here
End Using
using LegacyEntities = CompanyFoo.CoreLib.x86.VBComponents.CompanyObjects;
这被称为使用别名指令,正如你所看到的,它可以用于隐藏冗长的引用,如果你想在代码中明确表示你正在引用的内容,例如:
LegacyEntities.Account
替代
CompanyFoo.CoreLib.x86.VBComponents.CompanyObjects.Account
Account // It is not obvious this is a legacy entity