今天,你Try-Catch了吗?
引言:
高级语言中的异常处理很好用,对于有可能出错的代码我们用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了吗?的更多相关文章
- SQLServer如何添加try catch
在.net中我们经常用到try catch.不过在sqlserver中我们也可以使用try catch捕捉错误,在这里把语法记录下来和大家分享一下, --构建存储过程CREATE PROCEDURE ...
- try...catch..finally
try..catch..finally try{ 代码块1 }catch(Exception e){ 代码块2 }finally{ 代码块3 } catch是抓取代码块1中的异常 代码块2是出异常后的 ...
- C++异常处理:try,catch,throw,finally的用法
写在前面 所谓异常处理,即让一个程序运行时遇到自己无法处理的错误时抛出一个异常,希望调用者可以发现处理问题. 异常处理的基本思想是简化程序的错误代码,为程序键壮性提供一个标准检测机制. 也许我们已经使 ...
- POJ 3278 Catch That Cow(bfs)
传送门 Catch That Cow Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 80273 Accepted: 25 ...
- [c#基础]关于try...catch最常见的笔试题
引言 在翻看之前总结的常见面试题中,关于try...catch异常处理的还是蛮多了,今天看到这个面试题,也就重新学习一下. try..catch语法 try-catch语句由一个try块后跟一个或多个 ...
- 高程(4):执行环境、作用域、上下文执行过程、垃圾收集、try...catch...
高程三 4.2.4.3 一.执行环境 1.全局执行环境是最外层的执行环境. 2.每个函数都有自己的执行环境,执行函数时,函数环境就会被推入一个当前环境栈中,执行完毕,栈将其环境弹出,把控制器返回给之前 ...
- try catch里面try catch嵌套
try catch里能否内嵌try catch?答案是肯定的.但是等内层try catch出异常之后是个什么执行顺序呢?看下面代码 static void Main(string[] args) { ...
- 基础知识《十》java 异常捕捉 ( try catch finally ) 你真的掌握了吗?
本文转载自 java 异常捕捉 ( try catch finally ) 你真的掌握了吗? 前言:java 中的异常处理机制你真的理解了吗?掌握了吗?catch 体里遇到 return 是怎么处理 ...
- java try(){}catch(){}自动资源释放
从 Java 7 build 105 版本开始,Java 7 的编译器和运行环境支持新的 try-with-resources 语句,称为 ARM 块(Automatic Resource Manag ...
- Java throws Exception、try、catch
throws Exception是方法后面接的 意思是向上级抛出异常 try{}里面的异常会被外面的catch捕捉到 抛出异常是throw new Exception("异常"); ...
随机推荐
- DataTable和DataRow和DataColumn ~~~~~~~~~~[][]
DataSet.Tables[0].Rows[0][1]表示DataSet中第一张表(因为Tables[0]就是第一张表的意思)中第一行(Rows[0][]) 第二列(Rows[][1])的数据. D ...
- Goldengate升级之目标端(replicat端)升级
转自红黑联盟Goldengate升级之目标端(replicat端升级 要升级replicat端的原因为:目标端OGG软件版本与源端OGG软件版本不同,在实际生产应用中,经常发现replicat端事务丢 ...
- Kafka学习笔记(1)----Kafka的简介和Linux下单机安装
1. Kafka简介 Kafka is a distributed,partitioned,replicated commit logservice.它提供了类似于JMS的特性,但是在设计实现上完全不 ...
- 团体程序设计天梯赛-练习集-L1-027. 出租
L1-027. 出租 下面是新浪微博上曾经很火的一张图: 一时间网上一片求救声,急问这个怎么破.其实这段代码很简单,index数组就是arr数组的下标,index[0]=2 对应 arr[2]=1,i ...
- python tips: is同一性运算符
is用来判断两个对象是不是同一个对象,通过id()函数取对象地址进行判断.python会缓存一些小的整数,以及只包含字母数字以及下划线的字符串.所以在对于这些值的时候,is判断为True. >& ...
- python海龟的使用
############################螺旋正方形############################### import turtle turtle.left(90)for i ...
- kali 安装openvas
因为Kali Linux上没有默认安装OpenVas,因此只好自己摸索着安装了一遍. 如果没有设置过源(/etc/apt/sources.list),设置如下: deb http://http.kal ...
- java中String和int的互相转化
1. String 转 int 方式1:Integer.parseInt(); 方式2: Integer.valueOf(myStr).intValue(); 2. int 转String 方式1: ...
- Project Euler 31 1000-digit Fibonacci number( DP )
题意:在无限硬币的情况下能组成200的方案数有多少个 思路:DP,设数组 dp[ n ] [ k ] 代表前 n 种硬币能够组成 k 元的方案数,那么就能得到 dp [ n ] [ k ] = dp ...
- 洛谷 P1567 统计天数
题目背景 统计天数 题目描述 炎热的夏日,KC非常的不爽.他宁可忍受北极的寒冷,也不愿忍受厦门的夏天.最近,他开始研究天气的变化.他希望用研究的结果预测未来的天气. 经历千辛万苦,他收集了连续N(1& ...