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().


     

  • 相关阅读:
    129 01 Android 零基础入门 02 Java面向对象 06 Java单例模式 03 饿汉模式 VS 懒汉模式 02 懒汉式的代码实现
    128 01 Android 零基础入门 02 Java面向对象 06 Java单例模式 03 饿汉模式 VS 懒汉模式 01 饿汉式的代码实现
    127 01 Android 零基础入门 02 Java面向对象 06 Java单例模式 02 单例模式概述 01 单例模式的定义和作用
    126 01 Android 零基础入门 02 Java面向对象 06 Java单例模式 01 设计模式概述 01 设计模式简介
    125 01 Android 零基础入门 02 Java面向对象 05 Java继承(下)05 Java继承(下)总结 01 Java继承(下)知识点总结
    leetcode-----121. 买卖股票的最佳时机
    leetcode-----104. 二叉树的最大深度
    Json串的字段如果和类中字段不一致,如何映射、转换?
    Mybatis-Plus的Service方法使用 之 泛型方法default <V> List<V> listObjs(Function<? super Object, V> mapper)
    模糊查询
  • 原文地址:https://www.cnblogs.com/TivonStone/p/1756280.html
Copyright © 2011-2022 走看看