[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

时间: 2024-12-16 18:17:09

[C#6] 8-异常增强的相关文章

springmvc 通过异常增强返回给客户端统一格式

在springmvc开发中,我们经常遇到这样的问题:逻辑正常执行时返回客户端指定格式的数据,比如json,但是遇NullPointerException空指针异常,NoSuchMethodException调用的方法不存在异常,返回给客户端的是服务端异常堆栈信息,导致客户端不能正常解析数据:这明显不是我们想要的. 幸好从spring3.2提供的新注解@ControllerAdvice,从名字上可以看出大体意思是控制器增强.原理是使用AOP对Controller控制器进行增强(前置增强.后置增强.

集合并发修改异常-增强for循环,或者迭代器遍历的时候不可修改值

直接上代码: 无意间发现的://这个方法本身是为后面的集合去掉前面集合的重复数据一直报错,并发修改异常,仔细看mainList正在迭代循环,然后我进行了remove操作,这个时候就会报这个错.故:总结出了标题的结论public static List<GcallModel> distinctList(List<GcallModel> list, List<GcallModel> mainList){ for (GcallModel obj : mainList) { b

spreing 增强

1.前置增强 接口     类 public interface ISomeService { public void doSome(); } public class SomeService implements ISomeService { //核心业务 public void doSome(){ System.out.println("我们都要找到Java开发工作,薪资6,7,8,9,10K"); } } import org.springframework.aop.Method

Spring aop——前置增强和后置增强 使用注解Aspect和非侵入式配置

AspectJ是一个面向切面的框架,它扩展了java语言,定义了AOP语法,能够在编译期提供代码的织入,所以它有一个专门的编译器用来生成遵守字节码字节编码规范的Class文件 确保使用jdk为5.0以上版本. 01.使用注解标注增强(AspectJ)  :取代了配置文件中的aop:pointcut节点的配置 添加jar和log4j的配置文件 aspectj-1.8.7.jar aspectjweaver.jar 添加头文件: xmlns:aop="http://www.springframewo

《.NET 设计规范》第 7 章:异常

第 7 章:异常 异常与各种面向对象语言集成得非常好. 异常增强了 API 的一致性. 在用返回值来报告错误时,错误处理的代码与可能会发生错误的代码距离总是很近. 更容易使错误处理的带码全局化. 错误码很容易被忽略,而且经常会被忽略. 异常可以包含丰富的信息来对错误的原因加以描述. 异常允许用户定义未处理异常的处理程序. 异常可以包含丰富的信息来对错误额原因加以描述. 异常允许用户定义未处理异常的处理程序. 异常有助于检测. 7.1 抛出异常 不要返回错误码. 要通过抛出异常的放回来报告操作失败

spring中的增强类型

在spring中有两种增强方式:XML配置文件和注解配置.下面一次为大家讲解. 使用的是Aspectj第三方框架 纯POJO (在XML中配置节点) 使用@AspectJ,首先要保证所用的JDK 是5.0或以上版本 1)首先,创建一个切入点MyAspect,代码如下: 1 public class MyAspect { 2 // 前置通知 3 public void myBefore() { 4 System.out.println("这是前置增强"); 5 } 6 //前置通知带参

Spring学习(二十五)Spring AOP之增强介绍

课程概要: Spring AOP的基本概念 Spring AOP的增强类型 Spring AOP的前置增强 Spring AOP的后置增强 Spring AOP的环绕增强 Spring AOP的异常抛出增强 Spring AOP的引介增强 一.Spring AOP增强的基本概念 Spring当中的专业术语-advice,翻译成中文就是增强的意思. 所谓增强,其实就是向各个程序内部注入一些逻辑代码从而增强原有程序的功能. 二.Spring AOP的增强类型 首先先了解一下增强接口的继承关系 如上图

Spring(七)Spring中的四种增强和顾问

Spring中的四种增强有那四种? 前置增强    后置增强  环绕增强  异常增强 先编写接口和实体类  ISomeService和SomeServiceImpl package demo10; /** * Created by mycom on 2018/3/8. */ public interface ISomeService { public void doSome(); } package demo10; /** * Created by mycom on 2018/3/8. */ p

2018.3.10(动态代理 增强)

JDK动态代理: 准备一个接口ISomeService,接口中有一个方法doSome(),和一个这个接口的实现类SomeServiceImpl,并重写其中的方法 public interface ISomeService { public void doSome(); } public class SomeServiceImpl implements ISomeService { public void doSome() { System.out.println("我不是好人"); }

Sping(七)Sping四种增强和顾问

前置增强    后置增强  环绕增强  异常增强 先编写接口和实体类  ISomeService和SomeServiceImpl package demo10; /** * Created by mycom on 2018/3/8. */ public interface ISomeService { public void doSome(); } package demo10; /** * Created by mycom on 2018/3/8. */ public class SomeSe