新的“异常过滤器”功能提供? [英] What benefit does the new "Exception filter" feature provide?

查看:153
本文介绍了新的“异常过滤器”功能提供?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

C#6具有称为异常过滤的新功能



语法如下:



<$ p $($)$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $

$ $ c>

我不禁要问,这是有利于现在的方法:

  catch(Win32Exception异常)
{
if(exception.NativeErrorCode == 0x00042)
{
//在这里做某事
}
}

在卷曲之前过滤是一件很大的事情托架?也许是关于性能或安全性?

解决方案

C#6.0中的异常过滤器功能提供了各种好处。这是一些解释(按照我的重要性排序)




  • 功能奇偶校验 - 异常过滤器已经在IL级别和其他.NET语言(VB.Net& F#) [1] 中实现,并且作为构建C#和VB.Net(项目Roslyn)的新编译器的一部分


  • 崩溃转储 - 异常过滤器不修改堆栈。这意味着如果它被转储(在崩溃转储中),您将能够知道最初抛出异常的位置,而不仅仅是重新抛出异常(与实际问题无关) [3]


  • 调试 - 当异常进入 catch 块时,重新抛出使用 throw; 并且不会在堆栈中的任何其他地方处理(并且异常设置被设置为当异常是用户未处理时中断)调试器将在 throw; 而不是最初抛出异常的地方(即在下面的例子中,它会在 throw; 而不是code> throw new FileNotFoundException(); )


  • 多个 catch - 没有异常过滤器,您必须捕获异常,检查条件,如果不满足 throw; 异常。即使异常满足最终导致单个大 catch catch $ c>块

      try 
    {
    throw new FileNotFoundException();
    }
    catch(FileNotFoundException e)
    {
    if(!e.FileName.Contains(Hamster))
    {
    throw;
    }
    //处理
    }
    catch(异常e)
    {
    //无法访问的代码
    }


  • 可读性 - 虽然您可以使用catch all抓住阻止有许多条件和 throw; 当它们不满足(同时对堆栈进行修改时)更清晰地分开和不同 catch 块,其中每个块以适当的方式处理特定问题:

     尝试
    {
    }
    catch(Win32Exception异常)when(exception.NativeErrorCode == 0x00042)
    {
    }
    catch(Win32Exception exception)when( exception.NativeErrorCode == 0x00011)
    {
    }
    catch(IOException)
    {
    }


  • 滥用 - 您可以使用异常过滤器作为检查异常而不处理它的方法。虽然这不是主要的好处,但它是一个很好的副作用。你可以有一个错误的返回记录方法和一个空的 catch 块:

      private static bool LogException(异常异常)
    {
    Console.WriteLine(exception.Message);
    返回false;
    }

    尝试
    {
    }
    catch(ArgumentException异常)when(LogException(exception))
    {
    / /无法访问的代码。
    }




总之,的C#6.0功能是小的改进和语法糖,而异常过滤器不是一个很大的功能,它提供了以前不可能的功能。







  1. AC#6.0语言预览


    其他C#6.0中的异常改进 - 支持异常过滤器 - 将语言与其他.NET语言(即Visual Basic .NET和F#



  2. C#6和VB 14中的语言功能


  3. C#6中的新功能


    异常过滤器比因为他们离开堆栈而没有受到伤害,因此捕获和重新投掷。如果后来的异常导致堆栈被转储,您可以看到它最初来自哪里,而不仅仅是它被重新抛出的最后一个地方。




C# 6 has a new feature called "exception filtering"

The syntax is like this:

catch (Win32Exception exception) when (exception.NativeErrorCode == 0x00042)  
{  
    //Do something here 
}  

I couldn't help but wonder what the benefit of that is over the current approach:

catch (Win32Exception exception)   
{
     if (exception.NativeErrorCode == 0x00042)
     {
          //Do something here 
     }
}

Is it a big deal that filtering happen before the curly bracket? Perhaps in relation to performance or security?

解决方案

The Exception Filters feature in C# 6.0 provides various benefits. Here's an explanation of some (ordered by my perceived importance)

  • Feature Parity - Exception filters were already implemented in the IL level and the other .Net languages (VB.Net & F#)[1] and as part of building the new compiler for C# and VB.Net (project "Roslyn") many features existing in one language and lacking in the other were implemented[2].

  • Crash Dumps - Exception filters don't modify the stack. which means that if it gets dumped (in a crash dump) you would be able to know where the exception was originally thrown and not only where it was rethrown (which is irrelevant to the actual problem)[3]

  • Debugging - When an exception enters a catch block, rethrown using throw; and isn't handled anywhere else in the stack (and the exception settings are set to break when the exception is user-unhandled) the debugger would break on throw; instead of where the exception is originally thrown (i.e. in the example below it would break on throw; and not throw new FileNotFoundException();)

  • Multiple catch Blocks - Without exception filters you must catch the exception, check a condition and if it isn't met throw; the exception. The rethrown exception doesn't consider any other catch blocks even if the exception satisfies all the conditions which ultimately results in a single big catch block

    try
    {
        throw new FileNotFoundException();
    }
    catch (FileNotFoundException e)
    {
        if (!e.FileName.Contains("Hamster"))
        {
            throw;
        }
        // Handle
    }
    catch (Exception e)
    {
        // Unreachable code
    }
    

  • Readability - While you could use a "catch all" catch block with many conditions and throw; when they are not met (while suffering the modification to the stack) it's much clearer to have separate and distinct catch blocks where each handles a specific problem in the appropriate way:

    try
    {
    }
    catch (Win32Exception exception) when (exception.NativeErrorCode == 0x00042)  
    { 
    }  
    catch (Win32Exception exception) when (exception.NativeErrorCode == 0x00011)  
    {  
    }
    catch (IOException)
    {  
    }
    

  • "Abuse" - You could use exception filters as a way to inspect an exception without handling it. While this is not a main benefit it's a nice side effect. You can have a false-returning logging method and an empty catch block:

    private static bool LogException(Exception exception)
    {
        Console.WriteLine(exception.Message);
        return false;
    }
    
    try
    {
    }
    catch (ArgumentException exception) when (LogException(exception))  
    {
        // Unreachable code.
    }
    

In conclusion, most of C# 6.0 features are small improvements and syntactic sugar, and while exception filters isn't a very big feature it does provide functionality that wasn't possible before.


  1. A C# 6.0 Language Preview

    The other exception improvement in C# 6.0—support for exception filters—brings the language up-to-date with other .NET languages, namely Visual Basic .NET and F#

  2. Languages features in C# 6 and VB 14

  3. New Features in C# 6

    Exception filters are preferable to catching and rethrowing because they leave the stack unharmed. If the exception later causes the stack to be dumped, you can see where it originally came from, rather than just the last place it was rethrown.

这篇关于新的“异常过滤器”功能提供?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆