zoukankan      html  css  js  c++  java
  • More Effective C# Item5 : 确保泛型类型支持可销毁对象

        泛型中,约束能够为你和用户完成两件事情:1. 约束能将运行时错误转换成编译时错误;2. 约束为用户清楚的给出了实例化类型参数所必须实现的功能。不过约束却没有能够限制类型参数不能够做什么。好在大多数情况下,我们无需关系除了必要功能之外,类型参数还附带了哪些额外功能。

        但是如果泛型的约束中,包含了new约束,那么我们需要查看泛型参数是否实现了IDisposable接口。

        我们来看下面的代码。

    代码
    1 public interface IEngine
    2 {
    3 void DoWork();
    4 }
    5
    6  public class EngineDriver<T> where T : IEngine, new()
    7 {
    8 public void GetThingsDone()
    9 {
    10 T driver = new T();
    11 driver.DoWork();
    12 }
    13 }

        上述代码在执行后,如果T实现了IDisposable接口,那么很可能会造成资源泄漏,因为约束中并没有说明泛型参数需要实现IDisposable接口,因此从编译器的角度来看,是不会调用Dispose()方法的。这样无论何时初始化本地变量后,我们都需要检查T是否实现了IDisposable接口。

        下面是修改后的GetThingsDone()方法。

    1 public void GetThingsDone()
    2 {
    3 T driver = new T();
    4 using (driver as IDisposable)
    5 {
    6 driver.DoWork();
    7 }
    8 }

        上述代码在编译时会为driver分配一个本地变量,用来存放将driver强制转换为IDisposable后的结果。如果T没有实现IDisposable接口,那么本地变量就是null,这时编译器是不会调用Dispose()方法的;如果T实现了IDisposable接口,那么编译器将在该代码块的结束位置生成对Dispose()方法的调用。

        当然,针对上面提的问题,我们可以修改泛型类,使其实现IDisposable接口,来看下面的代码。

    代码
    1 public class EngineDriver<T> : IDisposable where T : IEngine, new()
    2 {
    3 private T driver = null;
    4 public void GetThingsDone()
    5 {
    6 if (driver == null)
    7 {
    8 driver = new T();
    9 }
    10 driver.DoWork();
    11 }
    12
    13 #region IDisposable Members
    14
    15 public void Dispose()
    16 {
    17 IDisposable temp = driver as IDisposable;
    18 if (temp != null)
    19 {
    20 temp.Dispose();
    21 }
    22 }
    23
    24 #endregion
    25 }

        需要注意,上述代码中,并不能保证不会重复调用driver的Dispose()方法,实现IDisposable接口的类,必须支持多次调用Dispose()方法,因为T并没有class约束,因此在离开Dispose()方法之前,并不能将driver设置为null。

        总结:有时,你可以通过重构并让泛型类中不再创建实例来解决这个问题。而对于必须要使用到局部变量的时候,则要提供必要的销毁代码。若是泛型类还需要支持对实现IDisposable接口的泛型参数进行延迟创建的话,那么将会带来更多的工作,但是这是不可缺少的。

        
    作者:李潘
             
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    Css实现漂亮的滚动条样式
    清除浮动的方式有哪些?比较好的是哪一种?
    Cookie、sessionStorage、localStorage的区别
    http和https的区别?
    git 拉取分支切换分支
    css 三角形
    js中??和?.的意思
    js this指向
    tsconfig.json配置
    查看本地安装的所有npm包
  • 原文地址:https://www.cnblogs.com/wing011203/p/1693349.html
Copyright © 2011-2022 走看看