解决方案
原因是 using
声明的目的是确保对象一旦超出范围就被处置,并且不需要显式代码来确保这种情况发生。
如在 理解 C# 中的“using”语句, ,.NET CLR 转换
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 (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
}
这 SqlConnection
将被关闭而不需要显式调用 .Close()
函数,这将会发生 即使抛出异常, ,无需 try
/catch
/finally
.
using 可用于调用 IDisposable。它还可以用于别名类型。
using (SqlConnection cnn = new SqlConnection()) { /*code*/}
using f1 = System.Windows.Forms.Form;
使用,在某种意义上
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();
}
您可以阅读有关我们的解决方案以及我们如何得出它的更多信息 这里.
我过去经常使用它来处理输入和输出流。您可以很好地嵌套它们,并且它可以消除您通常遇到的许多潜在问题(通过自动调用 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();
}
}
}
微软文档指出 使用 具有双重功能(https://msdn.microsoft.com/en-us/library/zhdeatwt.aspx),两者都作为 指示 并在 声明. 。作为一个 陈述, ,正如在其他答案中指出的那样,该关键字基本上是语法糖,用于确定处置范围 I一次性 目的。作为一个 指示, ,它通常用于导入命名空间和类型。另外,作为指令,您可以创建 别名 对于命名空间和类型,正如《C# 5.0 In a Nutshell》一书中指出的:权威指南”(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 最有趣的功能(在我看来)是,无论你如何退出 using 块,它总是会释放该对象。这包括退货和例外。
using (var db = new DbContext())
{
if(db.State == State.Closed) throw new Exception("Database connection is closed.");
return db.Something.ToList();
}
抛出异常或返回列表并不重要。DbContext 对象将始终被释放。
using 的另一个重要用途是实例化模式对话框。
Using frm as new Form1
Form1.ShowDialog
' do stuff here
End Using
总之,当您使用实现了以下类型的局部变量时 IDisposable
, 总是, ,无一例外地使用 using
1.
如果您使用非本地 IDisposable
变量,那么 总是 实施 IDisposable
图案.
两个简单的规则,无一例外1. 。否则,防止资源泄漏对于 *ss 来说是一个真正的痛苦。
1):唯一的例外是——当您处理异常时。那么调用的代码可能会更少 Dispose
明确地在 finally
堵塞。
有趣的是,您还可以将 using/IDisposable 模式用于其他有趣的事情(例如 Rhino Mocks 使用它的方式的另一点)。基本上,您可以利用编译器将 总是 对“已用”对象调用 .Dispose。如果您在某个操作后需要发生一些事情......有明确开始和结束的事物...那么您可以简单地创建一个 IDisposable 类,在构造函数中启动操作,然后在 Dispose 方法中完成。
这允许您使用非常好的 using 语法来表示所述操作的显式开始和结束。这也是 System.Transactions 的工作原理。
您可以通过以下示例来使用别名命名空间:
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
使用 ADO.NET 时,您可以将 keywork 用于连接对象或读取器对象等。这样,当代码块完成时,它将自动释放您的连接。
“using”也可以用来解决命名空间冲突。看 http://www.davidarno.org/c-howtos/aliases-overcoming-name-conflicts/ 我写了一篇关于这个主题的简短教程。
public class ClassA:IDisposable
{
#region IDisposable Members
public void Dispose()
{
GC.SuppressFinalize(this);
}
#endregion
}
public void fn_Data()
{
using (ClassA ObjectName = new ClassA())
{
//use objectName
}
}
使用 当您有一个资源在使用后想要处置时使用。
例如,如果您分配了一个文件资源,并且只需要在一段代码中使用它来进行少量读取或写入,则使用有助于在完成后立即处理文件资源。
正在使用的资源需要实现 IDisposable 才能正常工作。
例子:
using (File file = new File (parameters))
{
*code to do stuff with the file*
}
using 关键字定义对象的范围,然后在范围完成时释放该对象。例如。
using (Font font2 = new Font("Arial", 10.0f))
{
// use font2
}
看 这里 有关 C# using 关键字的 MSDN 文章。
并不是说它非常重要,但使用也可以用于动态更改资源。是的,如前所述,是一次性的,但也许您不希望在其余执行过程中资源与其他资源不匹配。所以你想处理掉它,这样它就不会干扰其他地方。
感谢下面的评论,我将稍微清理一下这篇文章(我当时不应该使用“垃圾收集”这个词,抱歉):
当您使用 using 时,它将在 using 作用域末尾调用对象上的 Dispose() 方法。因此,您可以在 Dispose() 方法中包含大量出色的清理代码。
这里有一个要点,希望可能会得到这个未标记的:如果您实现 IDisposable,请确保在 Dispose() 实现中调用 GC.SuppressFinalize(),否则自动垃圾收集将尝试在某个时刻出现并最终确定它,如果您这样做,这至少会浪费资源已经 Dispose()d 了。
立即处置该对象的合理使用的另一个例子:
using (IDataReader myReader = DataFunctions.ExecuteReader(CommandType.Text, sql.ToString(), dp.Parameters, myConnectionString))
{
while (myReader.Read())
{
MyObject theObject = new MyObject();
theObject.PublicProperty = myReader.GetString(0);
myCollection.Add(theObject);
}
}
大括号之外的所有内容都已被丢弃,因此如果您不使用对象,最好将其丢弃。之所以如此,是因为如果您有一个 SqlDataAdapter 对象,并且在应用程序生命周期中仅使用它一次,并且您只填充一个数据集并且不再需要它,则可以使用以下代码:
using(SqlDataAdapter adapter_object = new SqlDataAdapter(sql_command_parameter))
{
// do stuff
} // here adapter_object is disposed automatically
using 语句提供了一种正确使用 IDisposable 对象的便捷机制。通常,当您使用 IDisposable 对象时,应在 using 语句中声明并实例化它。using 语句以正确的方式调用对象上的 Dispose 方法,并且(当您如前面所示使用它时)它还会导致对象本身在调用 Dispose 时超出范围。在 using 块中,对象是只读的,不能修改或重新分配。
这来自: 这里
对我来说,“using”这个名字有点令人困惑,因为它可以是导入命名空间或语句(如此处讨论的)以进行错误处理的指令。
错误处理的不同名称会很好,而且也许是一个更明显的名称。
它还可用于创建示例范围:
class LoggerScope:IDisposable {
static ThreadLocal<LoggerScope> threadScope =
new ThreadLocal<LoggerScope>();
private LoggerScope previous;
public static LoggerScope Current=> threadScope.Value;
public bool WithTime{get;}
public LoggerScope(bool withTime){
previous = threadScope.Value;
threadScope.Value = this;
WithTime=withTime;
}
public void Dispose(){
threadScope.Value = previous;
}
}
class Program {
public static void Main(params string[] args){
new Program().Run();
}
public void Run(){
log("something happend!");
using(new LoggerScope(false)){
log("the quick brown fox jumps over the lazy dog!");
using(new LoggerScope(true)){
log("nested scope!");
}
}
}
void log(string message){
if(LoggerScope.Current!=null){
Console.WriteLine(message);
if(LoggerScope.Current.WithTime){
Console.WriteLine(DateTime.Now);
}
}
}
}
using 语句告诉 .NET 在不再需要时释放 using 块中指定的对象。因此,您应该对需要清理的类(例如 System.IO 类型)使用“using”块。
C#中using关键字有两种用法,如下所示。
- 作为指令
通常我们使用 using 关键字在代码隐藏和类文件中添加命名空间。然后它使当前页面中的所有类、接口和抽象类及其方法和属性都可用。
前任:
using System.IO;
- 作为声明
这是在 C# 中使用 using 关键字的另一种方法。它在提高垃圾收集性能方面发挥着至关重要的作用。using 语句确保即使在创建对象、调用方法、属性等时发生异常,Dispose() 也会被调用。Dispose() 是 IDisposable 接口中提供的一种方法,有助于实现自定义垃圾收集。换句话说,如果我正在执行一些数据库操作(插入、更新、删除),但不知何故发生异常,那么这里的 using 语句会自动关闭连接。无需显式调用连接 Close() 方法。
另一个重要因素是它有助于连接池。.NET 中的连接池有助于消除多次关闭数据库连接的情况。它将连接对象发送到池以供将来使用(下一次数据库调用)。下次从应用程序调用数据库连接时,连接池将获取池中可用的对象。因此它有助于提高应用程序的性能。因此,当我们使用 using 语句时,控制器会自动将对象发送到连接池,无需显式调用 Close() 和 Dispose() 方法。
您可以通过使用 try-catch 块执行与 using 语句相同的操作,并显式调用 finally 块内的 Dispose()。但 using 语句会自动进行调用,使代码更干净、更优雅。在 using 块中,对象是只读的,不能修改或重新分配。
前任:
string connString = "Data Source=localhost;Integrated Security=SSPI;Initial Catalog=Northwind;";
using (SqlConnection conn = new SqlConnection(connString))
{
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = "SELECT CustomerId, CompanyName FROM Customers";
conn.Open();
using (SqlDataReader dr = cmd.ExecuteReader())
{
while (dr.Read())
Console.WriteLine("{0}\t{1}", dr.GetString(0), dr.GetString(1));
}
}
在前面的代码中,我没有关闭任何连接,它会自动关闭。由于 using 语句(using (SqlConnection conn = new SqlConnection(connString)),using 语句将自动调用 conn.Close() ,对于 SqlDataReader 对象也是如此。而且如果发生任何异常,它会自动关闭连接。
欲了解更多信息--> https://www.c-sharpcorner.com/UploadFile/manas1/usage-and-importance-of-using-in-C-Sharp472/
这 Rhino Mocks 记录回放语法 有趣地利用了 using
.
用作语句自动调用在指定对象上的处置。该对象必须实现 IDisposable 接口。只要它们的类型相同,就可以在一个语句中使用多个对象。
CLR 将您的代码转换为 MSIL。using 语句被转换为 try 和finally 块。这就是 using 语句在 IL 中的表示方式。using 语句被翻译成三个部分:获取、使用和处置。首先获取资源,然后将其使用情况包含在带有finally 子句的try 语句中。然后该对象在finally 子句中被释放。
using 子句用于定义特定变量的范围。例如:
Using(SqlConnection conn=new SqlConnection(ConnectionString)
{
Conn.Open()
// Execute sql statements here.
// You do not have to close the connection explicitly here as "USING" will close the connection once the object Conn becomes out of the defined scope.
}