• [C#6] 8-异常增强


    0. 目录

    C#6 新增特性目录

    1. 在catch和finally块中使用await

    在C#5中引入一对关键字await/async,用来支持新的异步编程模型,使的C#的异步编程模型进一步的简化(APM->EAP->TAP->await/async,关于C#中的异步编程模型的不是本篇文章的介绍重点,详细的资料请移步这里Asynchronous Programming Pattern)。在C#5中虽然引入了await/async,但是却有一些限制,比如不能再catch和finally语句块中使用,C#6中将不再受此限制。

     1 using System;
     2 using System.Threading;
     3 using System.Threading.Tasks;
     4 
     5 namespace csharp6
     6 {
     7     internal class Program
     8     {
     9         private static void Main(string[] args)
    10         {
    11             do
    12             {
    13                 Log(ConsoleColor.White, "caller method begin", true);
    14                 CallerMethod();
    15                 Log(ConsoleColor.White, "caller method end");
    16             } while (Console.ReadKey().Key != ConsoleKey.Q);
    17         }
    18 
    19         public static async void CallerMethod()
    20         {
    21             try
    22             {
    23                 Log(ConsoleColor.Yellow, "try ", true);
    24                 throw new Exception();
    25             }
    26             catch (Exception)
    27             {
    28                 Log(ConsoleColor.Red, "catch await begin", true);
    29                 await AsyncMethod();
    30                 Log(ConsoleColor.Red, "catch await end");
    31             }
    32             finally
    33             {
    34                 Log(ConsoleColor.Blue, "finally await begin", true);
    35                 await AsyncMethod();
    36                 Log(ConsoleColor.Blue, "finally await end");
    37             }
    38         }
    39 
    40         private static Task AsyncMethod()
    41         {
    42             return Task.Factory.StartNew(() =>
    43             {
    44                 Log(ConsoleColor.Green, "async method begin");
    45                 Thread.Sleep(1000);
    46                 Log(ConsoleColor.Green, "async method end");
    47             });
    48         }
    49 
    50         private static void Log(ConsoleColor color, string message, bool newLine = false)
    51         {
    52             if (newLine)
    53             {
    54                 Console.WriteLine();
    55             }
    56             Console.ForegroundColor = color;
    57             Console.WriteLine($"{message,-20} : {Thread.CurrentThread.ManagedThreadId}");
    58         }
    59     }
    60 }

    运行结果如下:

    如果你细心的话会发现async method begin:6这一行的颜色居然不是我设置的绿色,而是白色,而且顺序也出现了错乱;而你再运行一次,它可能就是绿色了。这其实是由于我在Log方法(非线程安全的方法)里面的两行代码被多个线程争抢调用引起的:

    1 Console.ForegroundColor = color;
    2 Console.WriteLine($"{message,-20} : {Thread.CurrentThread.ManagedThreadId}");

    我们可以做点小改动来让Log方法做到线程安全(在C#中有很多方式可以做到,这只是其中一种):

     1 [MethodImpl(MethodImplOptions.Synchronized)]
     2 private static void Log(ConsoleColor color, string message, bool newLine = false)
     3 {
     4     if (newLine)
     5     {
     6         Console.WriteLine();
     7     }
     8     Console.ForegroundColor = color;
     9     Console.WriteLine($"{message,-20} : {Thread.CurrentThread.ManagedThreadId}");
    10 }

    貌似有点跑题了,回归正题,在catch和finally语句块中支持await关键字并不需要IL指令的支持,也不需要CLR的支持,而仅仅是编译器做出的代码转换(await/async就像lambda一样到delegate一样)。具体的IL就不做展开了,太庞大了,贴个图看下大致的情况:

    我们在CallerMethod中所写的代码,被转移到MoveNext中(更详细的资料请移步园友"Dev_Eric"的一篇博客:进阶篇:以IL为剑,直指async/await)(包括catch和finally中的await语句)。

    2. 异常过滤器

    其实这个语言特性在VB,F#里面早就支持了,现在C#6里面也可以使用了。

    1 try { … }
    2 catch (Exception e) when (filter(e))
    3 {
    4 5 }

    其中when这一块就是异常过滤器生效的地方,when后面跟一个表达式,表达式结果如果为true,则进入当前catch语句块。

    3. 参考

    Asynchronous Programming Patterns

    C# 6.0 await in catch/finally

    C# 6.0 Exception filters

    http://www.sadev.co.za/content/exception-filtering-c-6

  • 相关阅读:
    [leedcode 46] Permutations
    [leedcode 45] Jump Game II
    [leedcode 43] Multiply Strings
    [leedcode 42] Trapping Rain Water
    [leedcode 41] First Missing Positive
    [leedcode 40] Combination Sum II
    全排列
    [leedcode 39] Combination Sum
    [leedcode 38] Count and Say
    调和级数求和(分块)
  • 原文地址:https://www.cnblogs.com/linianhui/p/csharp6_exception-improvements.html
Copyright © 2020-2023  润新知