美文网首页
c# MoreLinq 之 Acquire

c# MoreLinq 之 Acquire

作者: wwmin_ | 来源:发表于2021-02-20 20:38 被阅读0次

    前言

    本系列是对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
    关于博主:评论和私信会在第一时间回复。或者[直接私信]我。
    版权声明:转载请注明出处!
    声援博主:如果您觉得文章对您有帮助,关注点赞, 您的鼓励是博主的最大动力!

    相关文章

      网友评论

          本文标题:c# MoreLinq 之 Acquire

          本文链接:https://www.haomeiwen.com/subject/eqrzxltx.html