加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 有没有理由使用Try / Catch与ExceptionThrown变量

发布时间:2020-12-15 04:05:41 所属栏目:百科 来源:网络整理
导读:我在 .Net Reference Source发现这个宝石,在 ButtonBase.cs在线408: bool exceptionThrown = true;try{ OnClick(); exceptionThrown = false; }finally{ if (exceptionThrown) { // Cleanup the buttonbase state SetIsPressed(false); ReleaseMouseCapture
我在 .Net Reference Source发现这个宝石,在 ButtonBase.cs在线408:
bool exceptionThrown = true;
try
{ 
    OnClick();
    exceptionThrown = false; 
}
finally
{
    if (exceptionThrown) 
    {
        // Cleanup the buttonbase state 
        SetIsPressed(false); 
        ReleaseMouseCapture();
    } 
}

问题是,什么会激励某人使用exceptionThrowwn标记,只是写它作为

try 
{
    OnClick();
}
catch
{
    SetIsPressed(false);
    ReleaseMouseCapture();
    throw;
}

是只是风格还是有一些副作用我失踪了?

解决方法

这个代码的原因是两倍.是的,格雷格提到,它不需要重新启动异常..但这不是真的原因.

真正的原因是语义之一.异常不应用于处理控制流.这是在处理一个事实,如果一个异常被抛出一个按钮,它可以使按钮视觉状态为“按下”.这不是真的“处理”的例外.这只是在抛出异常的情况下修正视觉问题.

这段代码并不在意什么是异常,它不想捕获所有异常,因为这是不好的做法.此外,代码没有做任何事情的例外..它只是说“嘿,如果我们得到了功能的结束,那么我们都很好,如果我们没有,那么让我们重置按钮状态只是为了确定”.

所以,这不是真正的异常处理,因此它没有捕获异常.它只是注意到抛出异常并进行了一些清理.

编辑:

这种方法可能不那么有争议,如果这样简单地重命名,删除任何对异常的引用,就会更有意义:

bool cleanupRequired = true;
try
{ 
    OnClick();
    cleanupRequired = false; 
}
finally
{
    if (cleanupRequired) 
    {
        // Cleanup the buttonbase state 
        SetIsPressed(false); 
        ReleaseMouseCapture();
    } 
 }

编辑:

为了支持我的评论,我写了以下测试程序来测试这些场景:

static void Main(string[] args)
{
    TimeSpan ts = new TimeSpan();
    TimeSpan ts2 = new TimeSpan();
    TimeSpan ts3 = new TimeSpan();
    TimeSpan ts4 = new TimeSpan();
    TimeSpan ts5 = new TimeSpan();
    TimeSpan ts6 = new TimeSpan();
    TimeSpan ts7 = new TimeSpan();
    TimeSpan ts8 = new TimeSpan();

    Stopwatch sw = new Stopwatch();

    // throw away first run
    for (int i = 0; i < 2; i++)
    {
        sw.Restart();
        try
        {
            throw new NotImplementedException();
        }
        catch
        {
            ts = sw.Elapsed;
        }
        sw.Stop();
        ts2 = sw.Elapsed;

        try
        {
            sw.Restart();
            try
            {
                throw new NotImplementedException();
            }
            finally
            {
                ts3 = sw.Elapsed;
            }
        }
        catch
        {
            ts4 = sw.Elapsed;
        }
        sw.Stop();
        ts5 = sw.Elapsed;

        try
        {
            sw.Restart();
            try
            {
                throw new NotImplementedException();
            }
            catch
            {
                ts6 = sw.Elapsed;
                throw;
            }
        }
        catch
        {
            ts7 = sw.Elapsed;
        }
        sw.Stop();
        ts8 = sw.Elapsed;
    }
    Console.WriteLine(ts);
    Console.WriteLine(ts2);
    Console.WriteLine(ts3);
    Console.WriteLine(ts4);
    Console.WriteLine(ts5);
    Console.WriteLine(ts6);
    Console.WriteLine(ts7);
    Console.WriteLine(ts8);
    Console.ReadLine();
}

我得到以下结果(我把它们分开,使它们更容易阅读):

00:00:00.0028424
00:00:00.0028453
00:00:00.0028354
00:00:00.0028401
00:00:00.0028427
00:00:00.0028404
00:00:00.0057907
00:00:00.0057951

最后3个显示当使用throw重新抛出异常时;它不会简单地传递现有的异常,它必须重新创建异常并重新抛出它,花费两倍的时间.

我们可以看到,捕获异常和捕获之间没有显着差异,而是使用finally.但是,重新开始这个例外就是成本来了.

这在VS 2012 Update 3中运行.

编辑:

没有调试器的时间.正如你所看到的那样,重新开始的价格仍然是两倍:

00:00:00.0000149
00:00:00.0000154
00:00:00.0000137
00:00:00.0000140
00:00:00.0000146
00:00:00.0000137
00:00:00.0000248
00:00:00.0000251

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读