c# MoreLinq 之 Acquire
2021-02-20 本文已影响0人
wwmin_
前言
本系列是对MoreLinq库的学习与总结,分析各个Api的实现方式及用法,也为能写出更高效的Linq打下基础。
1. Acquire 确保,保证
void AcquireTest()
{
Disposable a = null!;
Disposable b = null!;
Disposable c = null!;
var allocators = MoreEnumerable.From(() => a = new Disposable(),
() => b = new Disposable(),
() => throw new Exception(),
() => c = new Disposable()
);
allocators.Acquire();
}
class Disposable : IDisposable
{
public bool Disposed { get; private set; }
public void Dispose() { Disposed = true; }
}
static partial class MoreEnumerable
{
/// <summary>
/// Ensures that a source sequence of <see cref="IDisposable"/>
/// objects are all acquired successfully. If the acquisition of any
/// one <see cref="IDisposable"/> fails then those successfully
/// acquired till that point are disposed.
/// </summary>
/// <typeparam name="TSource">Type of elements in <paramref name="source"/> sequence.</typeparam>
/// <param name="source">Source sequence of <see cref="IDisposable"/> objects.</param>
/// <returns>
/// Returns an array of all the acquired <see cref="IDisposable"/>
/// objects in source order.
/// </returns>
/// <remarks>
/// This operator executes immediately.
/// </remarks>
//Acquire 顺序执行,如果失败则顺序释放资源
public static TSource[] Acquire<TSource>(this IEnumerable<TSource> source) where TSource : IDisposable
{
if (source == null) throw new ArgumentNullException(nameof(source));
var disposables = new List<TSource>();
try
{
disposables.AddRange(source);
return disposables.ToArray();//到此开始执行
}
catch
{
foreach (var disposable in disposables)
{
disposable.Dispose();//释放资源
}
throw;
}
}
//Evaluate
public static IEnumerable<T> Evaluate<T>(this IEnumerable<Func<T>> functions) =>
from f in functions ?? throw new ArgumentNullException(nameof(functions))
select f();
//From
public static IEnumerable<T> From<T>(params Func<T>[] functions)
{
if (functions == null) throw new ArgumentNullException(nameof(functions));
return Evaluate(functions);
}
}
这个方法主要实现的是:当Enumerable中有需要释放资源的对象时且有可能抛异常,使用这个方法之后能保证已经打开的对象能正确关闭。
在这个测试用例里使用了From方法,From方法实现动态调用执行,及调用了Evaluate方法,如下:
//Evaluate
public static IEnumerable<T> Evaluate<T>(this IEnumerable<Func<T>> functions) =>
from f in functions ?? throw new ArgumentNullException(nameof(functions))
select f();
本文作者:wwmin
微信公众号: DotNet技术说
本文链接:https://www.jianshu.com/p/32855aa37e12
关于博主:评论和私信会在第一时间回复。或者[直接私信]我。
版权声明:转载请注明出处!
声援博主:如果您觉得文章对您有帮助,关注点赞, 您的鼓励是博主的最大动力!