chiname

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 :: 管理 ::
先请大家看下面一段代码:
public static void Test(string fileName)
        
{
            
string fileName;
            System.IO.StreamReader sr
=null;
            
try
            
{
                sr
=new System.IO.StreamReader(fileName);                
            }

            
finally
            
{
                sr.Close();
            }

        }


以前我一直采用上面的方法关闭StreamReader, 我从没想到这样的写法在运行时会引起问题。今天我就遇到了莫明其妙的“未将对象引用设置到对象的实例”异常。因为这个异常很难跟踪,一开始我总是怀疑sr=new System.IO.StreamReader(fileName);后面的代码引起的异常,可是我将那部分代码全部注释, 还是有这个异常。后来,我注释掉sr.Close();才发现引起异常的真正原因。
原来在sr=new System.IO.StreamReader(fileName); 中,由于fileName路径不对,找不到相应的文件,抛出了异常,此时sr应该是null值,而在finally中执行sr.Close()就会引起“未将对象引用设置到对象的实例”异常。
正确的代码应该是这样:
public static void Test(string fileName)
        
{
            
string fileName;
            System.IO.StreamReader sr
=null;
            
try
            
{
                sr
=new System.IO.StreamReader(fileName);                
            }

            
finally
            
{
                
if(sr!=null)
                
{
                    sr.Close();
                }

            }

        }
posted on 2004-08-22 17:33 dudu 阅读(881) 评论(15)  编辑 收藏

评论:
# re: "finally"使用注意 2004-08-22 19:04 | Magicloud
这段代码是不是根本不需要使用try...finally。
因为在这里,您没有处理异常而任其抛出,所以写成:
sr = new System.IO.StreamReader(fileName);
sr.Close();
即可。如果第一句处有异常,则中断执行,且sr为null(不需要close);若无异常,则继续执行,sr会被close。

以上拙见,仅供参考。
  
# re: "finally"使用注意 2004-08-22 19:12 | dudu
对!
try语句中不应该包含sr=new System.IO.StreamReader(fileName);
这是我写代码时犯的错误。
应该在sr=new System.IO.StreamReader(fileName); 之后, 调用sr的时候使用try语句。
  
# re: "finally"使用注意 2004-08-22 19:58 | Ninputer
所以,应该直接用using。
  
# re: "finally"使用注意 2004-08-22 20:50 | 雪冬寒
try
{
   conn.Open();
   //do something
   conn.Close();
}
catch(Exception ex)
{
   //do something
}
finally
{
   if(conn.state == ConnctionState.Open)
   {
      conn.Close();
   }
}
  
# re: "finally"使用注意 2004-08-22 22:32 | 鞠强
agree to dudu,一般在C里面,我都是这么写的:

FileStream* fs = new FileStream(...);
try{
    fs->DoSomething();
}
__finally{
    delete fs;
}
  
# re: "finally"使用注意 2004-08-23 21:03 | 寒枫天伤
我觉得:
try
{
.....................
}
finally
{
....................
}
不能保证异常的捕获,它不承诺try中的代码可以真正能够完全执行,只要遇见任何跳转或结束当前程序块的指令时,就优先转向执行finally里的内容。

要保证程序的健壮性,应用如下形式:
try
{
........................
}
catch (Execption error)
{
.........................
}
Finally
{
.........................
}
省略掉catch,不是一个好习惯。

还有,StreamReader sr=null,并不是必要的,无论是否声明它为null,本身并没有多大的意义。
按vs.net2003的代码风格,直接书写 StreamReader sr,不会产生任何问题。

public static void Test(string fileName)
{
string fileName;
System.IO.StreamReader sr;
try
{
sr=new System.IO.StreamReader(fileName);
}
finally
{
sr.Close();
}
}
编译时,会有提示告诉你sr没有赋值,finally中的语句不能编译通过。
换而言之,如果不逼不得已,最好不要为初始化的值赋值为null,这样很容易让编译器路过某些必要的错误,引起代码隐患。

愚见仅供参考。
  
# re: "finally"使用注意 2004-08-23 22:33 | dudu
我的想法是:
这里的
try
{
sr=new System.IO.StreamReader(fileName);
}
finally
{
if(sr!=null)
{
sr.Close();
}
}
不是为了捕获异常, 而是为了保证不管是否发生异常都能执行sr.Close()。
如果需要捕获异常,的确需要加上catch语句。

System.IO.StreamReader sr=null;
也是逼不得已的做法, 不然无法编译通过。

  
# re: "finally"使用注意 2004-08-24 11:37 | Ninputer
@寒枫天伤 
我认为一般情况finally和catch均不应当同时出现。try finally和try catch完全是两种不同的目的,前者是为了将异常送出去,并执行所需代码,后者则是将异常拦截。我认为所有的try catch finally都可以分解为若干个try catch和try finally。
  
# re: "finally"使用注意 2004-08-24 11:40 | dudu
赞同Ninputer的观点!
  
# re: "finally"使用注意 2004-08-24 12:37 | sumtec
我觉得你这里的代码有点问题,不应该这样写。如果streamreader的构造出现问题,自然不可能close。因此我认为正确的写法应该是这样的:

try
{
   StreamReader sr = new StreamReader(filename);
   try
   {
      // Do something
   }
   finally
   {
      sr.Close();
   }
}
catch(Exception ex)
{
   MessageBox.Show("Damn it! I got an exception:\r\n" + ex.Message);
}
  
# re: "finally"使用注意 2004-08-25 12:18 | mysticApex
打开一个"流"之前,应该先检查这个文件是否存在。
  
# re: "finally"使用注意 2004-08-28 22:11 | 吕震宇
同意sumtec的说法。
  
# re: "finally"使用注意 2004-11-12 16:45 | 爽儿
同意mysticApex
应该检查文件的是否存在
  
# re: "finally"使用注意 2004-11-30 13:38 | inday
不止sr,还有很多,比如DataReader,如果在finally里关闭经常会出错,我觉得还是放在try里关闭比较好。
  
# re: "finally"使用注意 2005-03-18 15:57 | Evan
伙计们,除非万不得已的情况下,最好是不要使用Catch,这个命令太耗费资源了,我个人认为使用实例之前最好加个判断是否为null
posted on 2005-04-01 17:02  把我的欢乐带给你  阅读(345)  评论(0)    收藏  举报