引言:
高级语言中的异常处理很好用,对于有可能出错的代码我们用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;
}

正像老板说的:

最新文章

  1. strlen 字符型数组和字符数组 sizeof和strlen的区别 cin.get(input,Arsize)
  2. 循环打印i值(面试题)
  3. good excel website
  4. 转:Linux集群-----HA浅谈
  5. Java类加载器深入探索
  6. (三)结构体指针、sizeof
  7. Gridview中DataKeyNames 设置多个主键 取值
  8. IE8一枝独秀的JS兼容BUG
  9. MySQL datetime的更新,删除网上的一些老概念
  10. poj3268(置换矩阵思想)
  11. 『M&#246;bius函数与M&#246;bius反演』
  12. 不是说记住rm -rf的教训就够了
  13. cf219d 基础换根法
  14. maven 入门 (二)
  15. Kubernetes1.9 二进制版集群+ipvs+coredns
  16. atitit.软件gui按钮and面板---os区-----软链接,快捷方式
  17. C#.NET中使用BackgroundWorker在模态对话框中显示进度条
  18. libcurl 基本使用
  19. CSS选择器笔记,element element和element &gt; element 的区别
  20. shell编程3 ---流程控制语句

热门文章

  1. 【Oracle】搭建DG(DataGuard)
  2. 2017/01/07 学习笔记 jar包,maven
  3. 文件系统VFS数据结构(超级块 inode dentry file)(收集整理)
  4. win系统如何在桌面显示我的电脑
  5. C语言break/continue/exit/return的功能区别
  6. WTM
  7. jq DataTable
  8. 训练1-E
  9. 在windows环境中关于 pycharm配置 anaconda 虚拟环境
  10. 提高生产力:Web前端验证的标准化