zoukankan      html  css  js  c++  java
  • 浅尝EffectiveCSharp_8

    Item 15: Utilize using and try/finally for Resource Cleanup 使用using 和 try/finally 进行资源清理

    使用非托管系统资源的类型应该用Dispose()方法来释放。.NET环境的规则是:使用该类型的代码对它有释放的责任,而不是该类型或者系统。The  rules of the .NET environment make that the responsibility of the code that uses the type, not the responsibility of the type or the system.因此,当你使用的方法有Dispose()方法,那么你应该记得调用Dispose()方法来释放它。保证Dispose()的最好方法就是使用using声明或者是try/finally块。
    ●C#语言设计者知道明确的释放资源会是a common task。他们增加了关键字来使它更简单。加入你写了一下代码

    public void ExecuteCommand(string connString,string commandString)
    {
    SqlConnection myConnection
    = new SqlConnection(connString);
    SqlCommand mySqlCommand
    = new SqlCommand(commandString,myConnection);
    myConnection.Open();
    mySqlCommand.ExecuteNonQuery();
    }

     在这个例子中,两个可释放对象没有惊醒正确的清理:SqlConnection and SqlCommand。这些对象依然存在在内存中,直到finalizers被调用。下面是一个修改的例子

    public void ExecuteCommand(string connString,string commandString)
    {
    SqlConnection myConnection
    = new SqlConnection(connString);
    SqlCommand mySqlCommand
    = new SqlCommand(commandString,myConnection);
    myConnection.Open();
    mySqlCommand.ExecuteNonQuery();
    mySqlCommand.Dispose();
    myConnection.Dispose();
    }

    这个已经比较好了,除非SQL执行时出现了异常被抛出。那样的话,调用的Dispose()就不会发生。下面使用using声明来保证Dispose()被调用

    public void ExecuteCommand(string connString, string commandString)
    {
    using (SqlConnection myConnection = new SqlConnection(connString))
    {
    using (SqlCommand mySqlCommand = new SqlCommand(commandString, myConnection))
    {
    myConnection.Open();
    mySqlCommand.ExecuteNonQuery();
    }
    }
    }

    无论你什么时候在函数中使用一个可释放 的对象,使用using是保证对象释放的最简单方法。

     

    ●如果你对一个不支持IDisposable接口的变量使用using,编译器会产生一个错误。比如:如果obj实现IDisposable接口,using声明就会产生清楚代码。

    // Does not compile:
    // String is sealed, and does not support IDisposable.
    using (string msg = "This is a message")
    Console.WriteLine(msg);
    using声明只有在编译时类型支持IDisposable接口的情况下有用。
    // Does not compile.
    // Object does not support IDisposable.
    using (object obj = Factory.CreateResource())
    Console.WriteLine(obj.ToString());

    // The correct fix.
    // Object may or may not support IDisposable.
    object obj = Factory.CreateResource();
    using (obj as IDisposable)
    Console.WriteLine(obj.ToString());

    ●using声明是一个套一个。现在来看看try/catch块

    public void ExecuteCommand(string connString,
    string commandString)
    {
    SqlConnection myConnection
    = null;
    SqlCommand mySqlCommand
    = null;
    try
    {
    myConnection
    = new SqlConnection(connString);
    mySqlCommand
    = new SqlCommand(commandString,myConnection);
    myConnection.Open();
    mySqlCommand.ExecuteNonQuery();
    }
    finally
    {
    if (mySqlCommand != null)
    mySqlCommand.Dispose();
    if (myConnection != null)
    myConnection.Dispose();
    }
    }

     现在已经解决了两个非常显著的问题,但是这里还有点细微的差别。有的类型既支持Dispose方法也支持Close方法来释放对象。SqlConnection就是这样的一种类型。你也可以这样关闭SqlConnection:

    public void ExecuteCommand(string connString,
    string commandString)
    {
    SqlConnection myConnection
    = null;
    try
    {
    myConnection
    = new SqlConnection(connString);
    SqlCommand mySqlCommand
    = new SqlCommand(commandString,myConnection);
    myConnection.Open();
    mySqlCommand.ExecuteNonQuery();
    }
    finally
    {
    if (myConnection != null)
    myConnection.Close();
    }
    }

     这里connection并没有被关闭。Dispose方法和Close方法并不完全一样,Dispose在释放了资源后,还通知了GC去处理,它调用了GC.SuppressFinalize()。而Close没有这么做,因此对象依然在finalization队列。如果你能选择,Dispose() is better than Close().


     

  • 相关阅读:
    基于jquery的弹幕实现
    Cookie在顶级域名、二级域名和三级域名之间共享的情况
    报错:Win10 这台计算机中已经安装了 .NET Framework 4.5.2/4.6.1/4.7.1等等任何版本 或版本更高的更新
    Unity中的Text内容有空格导致换行
    逆波兰表达式
    Java基础03 byte[] 与 16进制字符串之间的转换
    nacos Linux 单机模式配置
    Oracle 常用SQL
    软件安装01 Linux下redis安装
    Java基础04 JSONObject 与范型对象转换
  • 原文地址:https://www.cnblogs.com/TivonStone/p/1756280.html
Copyright © 2011-2022 走看看