如何有效的在 LINQ 查询中处理异常?

咨询区

  • Jader Dias

参考下面的代码:

myEnumerable.Select(a => ThisMethodMayThrowExceptions(a));

如何保证在 Linq 的查询过程中即使抛出了异常,查询不会被提前中断,就好像在每层迭代上都有默认的 try catch 块。

回答区

  • LeBaptiste

我写了一个小的扩展方法,它可以实现在 IEnumerable<T> 中的每一层迭代上加上 try catch 异常处理逻辑, 扩展方法代码如下:

public static class OnCaughtExceptionExtension
{public static IEnumerable<SelectTryResult<TSource, TResult>> SelectTry<TSource, TResult>(this IEnumerable<TSource> enumerable, Func<TSource, TResult> selector){foreach (TSource element in enumerable){SelectTryResult<TSource, TResult> returnedValue;try{returnedValue = new SelectTryResult<TSource, TResult>(element, selector(element), null);}catch (Exception ex){returnedValue = new SelectTryResult<TSource, TResult>(element, default(TResult), ex);}yield return returnedValue;}}public static IEnumerable<TResult> OnCaughtException<TSource, TResult>(this IEnumerable<SelectTryResult<TSource, TResult>> enumerable, Func<Exception, TResult> exceptionHandler){return enumerable.Select(x => x.CaughtException == null ? x.Result : exceptionHandler(x.CaughtException));}public static IEnumerable<TResult> OnCaughtException<TSource, TResult>(this IEnumerable<SelectTryResult<TSource, TResult>> enumerable, Func<TSource, Exception, TResult> exceptionHandler){return enumerable.Select(x => x.CaughtException == null ? x.Result : exceptionHandler(x.Source, x.CaughtException));}public class SelectTryResult<TSource,TResult>{internal SelectTryResult(TSource source, TResult result, Exception exception){Source = source;Result = result;CaughtException = exception;}public TSource Source { get; private set; }public TResult Result { get; private set; }public Exception CaughtException { get; private set; }}
}

接下来就可以像下面这样使用了。

public void Test()
{List<string> completedProcesses = initialEnumerable.SelectTry(x => RiskyOperation(x)).OnCaughtException(exception => { _logger.Error(exception); return null; }).Where(x => x != null) // filter the ones which failed.ToList();
}

当然你有兴趣的话,还可以实现一个 SkipOnException 扩展方法,当在迭代中出现异常时自由选择是否可以跳过异常处理。

  • THTP

如果你 select 的是 IQueryable 类型,这时候你可能需要在 Expression 上扩展而不是 Lambda,参考如下扩展方法。

public static class ExpressionHelper
{public static Expression<Func<TSource, TResult>> TryDefaultExpression<TSource, TResult>(Expression<Func<TSource, TResult>> success, TResult defaultValue){var body = Expression.TryCatch(success.Body, Expression.Catch(Expression.Parameter(typeof(Exception)), Expression.Constant(defaultValue, typeof (TResult))));var lambda = Expression.Lambda<Func<TSource, TResult>>(body, success.Parameters);return lambda;}
}

然后像下面这样使用。

[Test]
public void Test()
{var strings = new object [] {"1", "2", "woot", "3", Guid.NewGuid()}.AsQueryable();var ints = strings.Select(ExpressionHelper.TryDefaultExpression<object, int>(x => Convert.ToInt32(x), 0));Assert.IsTrue(ints.SequenceEqual(new[] {1, 2, 0, 3, 0}));
}

点评区

其实面对这种场景,我第一个想到的还是 Polly 框架,大家有兴趣可以看一看:https://github.com/App-vNext/Polly

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/290439.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

rman备份,crontab计划任务没有生成备份文件

利用crontab 执行计划和RMAN结合来实现 数据库的自动备份现象&#xff1a;利用计划任务来执行备份&#xff0c;只是生成了目录&#xff0c;却没有生成备份文件1&#xff1a; 手动执行备份脚本&#xff0c;没有问题2&#xff1a;crontab 计划任务&#xff0c;能够生成目录&#…

C和指针之函数之求参数列表中的最大值

1、问题 *编写一个叫max_list函数&#xff0c;它用于检查任意数目的整形参数*并返回他们中的最大值&#xff0c;参数列表必须以一个负数结尾&#xff0c;提*示列表的结束2、代码实现 #include <stdio.h> #include <stdarg.h> /***编写一个叫max_list函数&#xff0…

fir.im 持续集成技术实践

互联网时代&#xff0c;人人都在追求产品的快速响应、快速迭代和快速验证。不论是创业团队还是大中型企业&#xff0c;都在探索属于自己的敏捷开发、持续交付之道。fir.im 团队也在全面实施敏捷&#xff0c;并推出新持续集成服务— flow.ci &#xff0c;以帮助企业将开发测试流…

Redis调用及使用

首先第一步&#xff1a; 添加引用1.ServiceStack.DLLServiceStack.Interfaces.DLLServiceStack.ServiceInterface.DLL以上引用都可以在网上下载到2.调用&#xff1a;demo&#xff1a; stringticket "" ;stringhost "localhost" ;stringelementKey "…

MYSQL-skip-networking

1、跳过tcp/ip协议通信&#xff1a;[mysqld]# The TCP/IP Port the MySQL Server will listen onport3306#log_outputTABLEskip-networking #添加这一行然后重启服务2、测试连接&#xff1a;C:\Documents and Settings\Administrator>mysql -u root -pEnter password:ERROR…

宇宙最強的IDE - Visual Studio 25岁生日快乐

每位开发者从入门开始或多或少都会接触过 Visual Studio &#xff0c; 现今的 Visual Studio 除了支持传统的 C , C# , Visual Basic.NET ,F# 的编程语言外&#xff0c;还可以做 Python , Node.js 的开发。在应用场景上也从单一的桌面应用&#xff0c;延伸到 Web &#xff0c; …

C和指针之实现可变参数函数编译出现expanded from macro ‘va_arg‘ #define va_arg(ap, type) 解决办法

1、问题 编译可变参数函数里面有va_arg函数的时候提示这个错误 expanded from macro va_arg #define va_arg(ap, type) 2、原因 我没有考虑“默认参数提升”问题 如果一个函数的形参类型未知, 例如使用了Old Style C风格的函数声明,或者函数的参数列表中有 ...,那么调…

有没有一段代码,让你觉得人类的智慧也可以璀璨无比?【转】

转自&#xff1a;https://www.zhihu.com/question/30262900 作者&#xff1a;烧茄子链接&#xff1a;https://www.zhihu.com/question/30262900/answer/48741026来源&#xff1a;知乎著作权归作者所有。商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处。当然是这个…

maven中pom.xml中的scope讲解

一、compile&#xff1a;编译范围compile是默认的范围&#xff1b;如果没有提供一个范围&#xff0c;编译范围依赖在所有的classpath 中可用&#xff0c;同时它们也会被打包。而且这些dependency会传递到依赖的项目中。 二、provided&#xff1a;已提供范围provided 明了depend…

C和指针之函数之实现简单的printf函数(支持%d, %f, %c, %s)

1、问题 *简化printf函数,能够处理%d, %f, %c, %s格式码,假设已经存在 *print_integer和print_float函数,另外2个类型用put char来打印 思路: void va_start(va_list ap, last);// 取第一个可变参数的指针给ap,// last是函数声明中的最后一个固定参数(比如printf函数原型…

python 面试宝典--集各家之所长,乱七八糟于一体

1. 在判断object是否是class的instances时&#xff0c;type和isinstance函数的区别&#xff1f; type(obj) > <type instance> type(cls) > <type classobj> 由上可知&#xff0c;所有obj type后统一为 instance type&#xff1b; 而cls type后统一为classob…

如何使用 abp 创建 module 并应用单独的数据库迁移

最近在学习使用 abp 来做一些小程序。abp 是一个功能丰富的 .NET 开发框架&#xff0c;完全开源&#xff0c;遵循 DDD&#xff08;领域驱动&#xff09;设计模式&#xff0c;支持微服务开发&#xff0c;集成了 Identity、角色权限、本地化、动态代理、后台任务、分布式消息、审…

MinGW安装和使用基础教程

MinGW全称Minimalist GNU For Windows&#xff0c;是个精简的Windows平台C/C、ADA及Fortran编译器&#xff0c;相比Cygwin而言&#xff0c;体积要小很多&#xff0c;使用较为方便。MinGW提供了一套完整的开源编译工具集&#xff0c;以适合Windows平台应用开发&#xff0c;且不依…

px,em,rem,vw单位在网页和移动端的应用

px&#xff1a; 是网页设计中最常用的单位&#xff0c;然而1px到底是多大长&#xff0c;恐怕没有人能回答上来 它用来表示屏幕设备物理上能显示的最小的一个点&#xff0c;这个点不是固定宽度的&#xff0c;不同设备上点的长度、比例有可能会不同。 假设&#xff1a;你现在用的…

C和指针之函数递归实现把amount表示的值转换为单词形式written_amount(unsigned int amount,char *buffer)

1、题目 编写函数 void written_amount(unsigned int amount,char *buffer); 它把amount表示的值转换为单词形式,并储存于buffer中。这个函数可以在一个打印支票的程序中使用。例如,如果amount的值是16312,那么buffer中存储的字符串应该是 SIXTEEN THOUSAND THREE HUNDR…

cs-Panination

ylbtech-Unitity: cs-PaninationPager.cs IPagingOption.cs IPagedList.cs PagingOption.cs PagedList.cs PagingExtensions.cs 1.A,效果图返回顶部 1.B,源代码返回顶部1.B.1,Pager.cs using System; using System.Collections.Generic; using System.Linq; using System.Text…

SignalR的使用

什么是 SignalR&#xff1f;ASP.NET Core SignalR 是一个开放源代码库&#xff0c;可用于简化向应用添加实时 Web 功能。实时 Web 功能使服务器端代码能够将内容推送到客户端。适合 SignalR 的候选项&#xff1a;需要从服务器进行高频率更新的应用。示例包括游戏、社交网络、投…

NHibernate之旅(7):初探NHibernate中的并发控制

本节内容 什么是并发控制&#xff1f; 悲观并发控制(Pessimistic Concurrency)乐观并发控制(Optimistic Concurrency)NHibernate支持乐观并发控制实例分析结语什么是并发控制&#xff1f; 当很多人试图同一时候改动数据库中的数据时&#xff0c;必须实现一个控制系统&#xff0…

C和指针之数组名和数组名和首元素以及sizeof(数组名)和sizeof(数组名作为参数)区别

1、先看我的测试Demo #include <stdio.h> #include <stdlib.h>int get_size(int *p) {int size = sizeof(p);return size; }int main() {int a[6] = {1, 2, 3, 4, 5, 6};int b[] = {1, 2, 3, 4, 5, 6};int c[10] = {1, 2, 3, 4, 5, 6};int size_a = sizeof(a);int …

html常用标签(form标签)

一、form标签 form标签是html标签中非常重要的一个标签。常用于注册、登录页面的使用。 <form action"提交地址" method"提交方式"> </form> 注&#xff1a;method的值有两个。get&#xff08;默认值&#xff09;和post。get数据安全性没有pos…