为何C#代码中ArgumentOutOfRangeException未被catch语句捕获?
LINQ延迟执行导致异常未被捕获的原因
先看这段出问题的C#代码:
try { return Enumerable.Range(0, indexes.Count).Select(i => dataRows[indexes[i]]); } catch (ArgumentOutOfRangeException ex) { return null; }
之所以ArgumentOutOfRangeException没被当前的catch捕获,核心原因是LINQ的延迟执行特性:
Select方法返回的是IEnumerable<T>类型的查询对象,它不会在调用Select的当下执行dataRows[indexes[i]]的逻辑。- 这段代码的
return语句只是返回了一个“待执行”的查询,真正的元素访问逻辑要等到外部代码枚举这个集合时(比如调用ToList()、用foreach遍历)才会触发。
也就是说,异常根本不是在当前的try块里抛出的,自然不会被这里的catch接住。等异常真正触发时,程序已经脱离了这个try-catch的作用范围。
解决办法
如果想让异常在当前方法的try-catch里被捕获,最简单的方式是强制立即执行查询,把结果转换成具体的集合类型,比如List<T>:
try { return Enumerable.Range(0, indexes.Count).Select(i => dataRows[indexes[i]]).ToList(); } catch (ArgumentOutOfRangeException ex) { return null; }
如果必须返回延迟执行的IEnumerable<T>,那只能把异常处理逻辑放到Select的委托内部,或者在外部枚举这个集合的时候再做异常捕获——但这样当前方法的try-catch就起不到作用了。
内容的提问来源于stack exchange,提问作者T. J. Fan
相关产品推荐
相关产品推荐

