引言:
高级语言中的异常处理很好用,对于有可能出错的代码我们用Try-Catch包起来,就能保证系统健壮的运行了,但是你的Try-Catch用对了吗?

  

今天code review的时候,老板给我提了个问题,让我不要用Try-Catch。原话是这样的:

然后我就想,为什么不让try catch啊,如果不try catch程序出错时不就down了吗,用户连出错信息都得不到,这样的系统也太不友好了吧?

然后老板又跟我解释了,原话如下:

  老板在西雅图的微软干了10来年,我是还没毕业的菜鸟,对老板说的话自然是不敢贸然怀疑的,于是乖乖改了代码。但是不安分的内心还是驱使我到网上搜了一下,不搜不知道,原来网上对于这个问题早已是讨论了千八百遍。

  

总结了10几个来自StackOverflow的回答,大致意思如下:

问题一:使用try catch会不会影响程序运行效率?

解释:

static public void Main(string[] args)
{
Stopwatch w = new Stopwatch();
double d = ; w.Start(); for (int i = ; i < ; i++)
{
try
{
d = Math.Sin();
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
} w.Stop();
Console.WriteLine(w.Elapsed);
w.Reset();
w.Start(); for (int i = ; i < ; i++)
{
d = Math.Sin();
} w.Stop();
Console.WriteLine(w.Elapsed);
}
Output:
::00.4269033 // with try/catch
::00.4260383 // without.

  

  这个实例说明了并不像有的人说的那样,try catch并不会影响代码的执行效率。但是注意,上面这个实例catch块里并没有rethrow;继续看下面这个示例:

private void TryCatchPerformance()
{
  int iterations = ;   Stopwatch stopwatch = Stopwatch.StartNew();
  int c = ;
  for (int i = ; i < iterations; i++)
  {
  try
{
// c += i * (2 * (int)Math.Floor((double)i));
  c += i * ;
}
catch (Exception ex)
{
throw;
}
}
stopwatch.Stop();
WriteLog(String.Format("With try catch: {0}", stopwatch.ElapsedMilliseconds)); Stopwatch stopwatch2 = Stopwatch.StartNew();
int c2 = ;
for (int i = ; i < iterations; i++)
{
// c2 += i * (2 * (int)Math.Floor((double)i));
c2 += i * ;
}
stopwatch2.Stop();
WriteLog(String.Format("Without try catch: {0}", stopwatch2.ElapsedMilliseconds));
}
Output:
With try catch:
Without try catch:

结果显示好像有影响啊,两倍啊!高兴太早了,把for循环里的计算语句稍微做下改动,变为

c += i * ( * (int)Math.Floor((double)i));

结果显示为:

Output:
With try catch:
Without try catch:

希望破灭了,看来有没有影响还有try块里执行的内容有关。但是大量的实验说明影响是很小的。

问题二:既然try-catch不影响效率,那么为什么不提倡像下面这样使用?

public static string SerializeDTO(DTO dto) {
try {
XmlSerializer xmlSer = new XmlSerializer(dto.GetType());
StringWriter sWriter = new StringWriter();
xmlSer.Serialize(sWriter, dto);
return sWriter.ToString();
} catch(Exception ex) {
throw ex;
}
}

解释:

  首先要讲一个问题:如果这段代码的try块里出了问题,那么程序是要down掉的,因为在catch块里throw了Exception,并没有消化掉,如果去掉这个throw 那么在try块出问题的情况下程序也不会down掉了。像下面这样:

public static string SerializeDTO(DTO dto) {
try {
XmlSerializer xmlSer = new XmlSerializer(dto.GetType());
StringWriter sWriter = new StringWriter();
xmlSer.Serialize(sWriter, dto);
return sWriter.ToString();
} catch(Exception ex) {
}
}

虽然这样写程序不会down掉,但有意思的是:这种写法也不推荐。
  

第一种写法不推荐的原因如下:
try块里抛出的异常信息(有可能是SqlException之类的)被catch块包装成了Exception重新抛出,屏蔽掉了原本的出错信息,在fix bug的时候不好找原因。

第二种写法不推荐的原因如下:
这种写法程序不会down掉,因为catch块把出错信息消化掉了。这样有很不好的后果是:debug的时候找不到真正的错误源头在哪里!!

问题三:提倡的写法是什么?

答案:

try { ... }
catch { throw; }

  但是这样写和不用try-catch有什么不同么?根本没有!所以通常的做法是如果需要log出错信息时,才使用try-catch,像下面这样写:

try
{
// code that may throw exceptions
}
catch
{
// add error logging here
throw;
}

正像老板说的:

今天,你Try-Catch了吗?的更多相关文章

  1. SQLServer如何添加try catch

    在.net中我们经常用到try catch.不过在sqlserver中我们也可以使用try catch捕捉错误,在这里把语法记录下来和大家分享一下, --构建存储过程CREATE PROCEDURE ...

  2. try...catch..finally

    try..catch..finally try{ 代码块1 }catch(Exception e){ 代码块2 }finally{ 代码块3 } catch是抓取代码块1中的异常 代码块2是出异常后的 ...

  3. C++异常处理:try,catch,throw,finally的用法

    写在前面 所谓异常处理,即让一个程序运行时遇到自己无法处理的错误时抛出一个异常,希望调用者可以发现处理问题. 异常处理的基本思想是简化程序的错误代码,为程序键壮性提供一个标准检测机制. 也许我们已经使 ...

  4. POJ 3278 Catch That Cow(bfs)

    传送门 Catch That Cow Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 80273   Accepted: 25 ...

  5. [c#基础]关于try...catch最常见的笔试题

    引言 在翻看之前总结的常见面试题中,关于try...catch异常处理的还是蛮多了,今天看到这个面试题,也就重新学习一下. try..catch语法 try-catch语句由一个try块后跟一个或多个 ...

  6. 高程(4):执行环境、作用域、上下文执行过程、垃圾收集、try...catch...

    高程三 4.2.4.3 一.执行环境 1.全局执行环境是最外层的执行环境. 2.每个函数都有自己的执行环境,执行函数时,函数环境就会被推入一个当前环境栈中,执行完毕,栈将其环境弹出,把控制器返回给之前 ...

  7. try catch里面try catch嵌套

    try catch里能否内嵌try catch?答案是肯定的.但是等内层try catch出异常之后是个什么执行顺序呢?看下面代码 static void Main(string[] args) { ...

  8. 基础知识《十》java 异常捕捉 ( try catch finally ) 你真的掌握了吗?

    本文转载自  java 异常捕捉 ( try catch finally ) 你真的掌握了吗? 前言:java 中的异常处理机制你真的理解了吗?掌握了吗?catch 体里遇到 return 是怎么处理 ...

  9. java try(){}catch(){}自动资源释放

    从 Java 7 build 105 版本开始,Java 7 的编译器和运行环境支持新的 try-with-resources 语句,称为 ARM 块(Automatic Resource Manag ...

  10. Java throws Exception、try、catch

    throws Exception是方法后面接的 意思是向上级抛出异常 try{}里面的异常会被外面的catch捕捉到 抛出异常是throw new Exception("异常"); ...

随机推荐

  1. APP开发过程的优惠券设计及流程

    在整个APP开发产品发展的整个周期中,运营活动必不可少,而发放优惠券已成为运营活动的一种基本形式,而关于优惠券设计的整体流程尤为重要.接下来,常州开发APP公司专家分享一下自己的经验,希望对大家有帮助 ...

  2. C#中的引用传递和值传递。

    最近在写项目中有同事碰到这样的传值问题,可能很多对这个参数的传递还有点疑惑,自己也是对这个基础知识做一个回顾和巩固. 首先什么是值类型和引用类型可以去园里看一下相关的资料,都有介绍. 常用值类型包括: ...

  3. 三维重建:QT+OpenNI+Kinect图像校正

    后记: 当时能不放弃这个方向是因为这里面涉及了一种很有效的三位场景存储方式,可能给出除图元建模之外的一种三维场景描述方式.这和Flash与位图的对比一样,基于图元的flash始终抵不过基于点描述的位图 ...

  4. Robot Framework(四)创建测试套件

    2.3.1测试用例文件 Robot Framework测试用例是使用测试用例文件中的测试用例表创建的.这样的文件会自动从它包含的所有测试用例中创建一个测试套件.可以有多少测试用例没有上限,但建议少于1 ...

  5. JS 20180415作业

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  6. [NOI2005]维护数列_Splay

    真的毫无算法可言,就是比谁的码力强罢了... Code: #include<stack> #include<cstdio> #include<algorithm> ...

  7. python二级登陆菜单

    """ 1.三级菜单 注册 登陆 注销 2.进入每一个一级菜单,都会有下一级的菜单"""user_item = dict()try: whi ...

  8. 何为JQuery对象?

  9. Ubuntu 终端配置

    安装zsh apt install zsh 设置zsh为默认shell chsh -s /bin/zsh 恢复 bash 使用 chsh -s /bin/bash 安装 Oh My Zsh sh -c ...

  10. MySQL 数据库类型