zoukankan      html  css  js  c++  java
  • 异常安全在Java和C#语言中的简化

    C簇语言中,C++首先在引入异常。在C++标准委员会投票之时,英国代表提出了反对意见,他们说异常差不多破坏了每个程序。如下的代码片段很好地展示了异常是如何把事情搞乱的

    void f()
    {
     T
    * p = new T;
     
    // 一些处理
     delete p;
    }

    如果处理过程引发异常抛出,那么语句“delete p;”便不会被执行,这就导致了内存泄漏。为解决这个问题,有两个提议,“智能指针”和垃圾收集。

    英国人的反对意见是有道理,在C++中编写异常安全的代码,曾经困扰C++社群数年,97年至99年,终于总结了一些比较好的解决办法。至今为止,仍然是十分困难的事情。

    Java和C#是一门大众化的语言,异常安全这么困难的技术,大多数程序员都会比较难以掌握,所以引入了一些简化的方式。

    在Java中,引入了垃圾收集的技术,程序员不用关心内存的回收问题了。但是还是存在其他的一些资源,例如数据库连接、文件句柄、互斥体(Mutex)等等。Java中,为了简化对互斥体(Mutex)使用,引入了synchronized关键字(类似C#中的lock),使得线程的使用变得简单。如下:

    public synchronized void f1(List list) {
     synchronized (list) 
    {
        
    //do something
     }

    }

    在C#中,则是更进了一步。为了解决异常安全问题,引入了lock、using两个关键字管理资源。lock与Java中的synchronized对应。

    Object obj = new Object();
    lock (obj)
    {
        
    //do something
    }

    上述代码在不用lock的时候,是这样写的:

    System.Threading.Monitor.Enter(obj);
    try
    {
        
    //do something
    }

    finally
    {
        System.Threading.Monitor.Exit(obj);
    }

    而using则是一种和IDisposable配合使用的特别方式,或许是一种创新。
    我们先看看IDisposable接口:

    public interface IDisposable
    {
          
    // Methods
          void Dispose();
    }


    我们看看数据连接SqlConnection的实现,SqlConnection实现了IDisposable接口,SqlConnection中大约是这样实现:

    if (disposing)
    {
          
          
          
    this.Close();
    }

    在Dispose中调用了Close方法,释放了资源。在File相关的对象,也是以类似的方式处理的。

    使用Using:

    using (IDbConnection conn = new SqlConnection())
    {
        
    // do something
    }

    如果不是用Using,也需要保证异常安全。可以这样写,与上面的代码等价:

    IDbConnection conn = new SqlConnection();
    try
    {
        
    // do something
    }

    finally
    {
        IDisposable disposableObj 
    = conn as IDisposable;
        
    if (disposableObj != null)
        
    {
            disposableObj.Dispose();
        }

    }

    当然更直接的代码是:

    IDbConnection conn = new SqlConnection();
    try
    {
        
    //do something
    }

    finally
    {
        conn.Close();
    }

    在C#中,using的用法,并没有走到多远,其实就是try ... finally方式和IDiposible接口的配合使用。

    其实foreach的关键字也起到简化编写异常安全代码的作用:

    IList list = new ArrayList();
    foreach (Object obj in list)
    {
        
    //do something 
    }

     其实相当于:

    IList list = new ArrayList();
    IEnumerator iter 
    = list.GetEnumerator();
    try
    {
        
    while (iter.MoveNext())
        
    {
            Object obj 
    = iter.Current;
            
    //do something 
        }

    }

    finally
    {
        IDisposable disposableObj 
    = iter as IDisposable;
        
    if (disposableObj != null)
        
    {
            disposableObj.Dispose();
        }

    }

    在foreach中,也使用了try ... finally,用于Dispose实现了IDisposable的IEnumerator对象。

    Anders Hejlsberg曾说,在优秀的代码中,会有大量的try...finally形式的代码存在。为了减少try...finally的使用,C#引入了lock、using、foreach。

    但是异常处理在C#中,缺少了异常规范(exception specification),这是令人遗憾,Anders Hejlsberg曾经发表过一些论述,很有道理,但是没有异常规范的C#是令人遗憾的。

  • 相关阅读:
    BootStrap 智能表单系列 五 表单依赖插件处理
    BootStrap 智能表单系列 四 表单布局介绍
    BootStrap 智能表单系列 三 分块表单配置的介绍
    LinQ.OrderBy 多个字段排序
    ABP.NET CORE 遇到的小问题
    vs2017断点无效 当前不会命中断点 已设置断点单还未绑定
    DateTime 取年月日;字符串截取
    C# DateTime 多个时间段循环相加;两个时间段求差值
    ABP.Net Core 小白使用教程 附件:ABP.NET中文文档
    ASP.NET MVC+Easyui 后台管理系统的图片上传
  • 原文地址:https://www.cnblogs.com/jobs/p/25367.html
Copyright © 2011-2022 走看看