我正在检查Jon Skeet的MoreLinq,我对获取扩展源代码感到好奇
将实现如下
/// <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"/>
/// object and in source order.
/// </returns>
/// <remarks>
/// This operator executes immediately.
/// </remarks>
public static TSource[] Acquire<TSource>(this IEnumerable<TSource> source)
where TSource : IDisposable
{
if (source == null) throw new ArgumentNullException("source");
var disposables = new List<TSource>();
try
{
disposables.AddRange(source);
return disposables.ToArray();
}
catch
{
foreach (var disposable in disposables)
disposable.Dispose();
throw;
}
}
Run Code Online (Sandbox Code Playgroud)
根据我的理解,它会收到一个IEnumerable<IDisposable>并创建一个List<IDisposable>.
我无法理解这里可能出现的问题.
任何人都可以向我解释,并可能提供一个这种扩展有用的例子吗?
p.s*_*w.g 15
AddRange迭代的调用source.如果出于任何原因遇到异常,则先前获得的任何异常将被处置.考虑这个例子:
var filenames = new[] { "file1.xml", "file2.xml", "doesnotexist.xml" };
var disposables = filenames.Select(fn => File.OpenRead(fn));
var fileStreams = disposables.Acquire();
Run Code Online (Sandbox Code Playgroud)
disposables由于懒惰的评估,在您分配时不会抛出任何异常.但是,当对AddRange内部的调用Aquire到达第三个元素(它尝试打开的位置"doesnotexist.xml")时,FileNotFoundException将抛出一个.发生这种情况时,Acquire将安全地处理以前的流.一个简单ToList/ ToArray将使前两个文件流保持打开状态.
从本质上讲,Acquire是否确保所有文件filenames都安全地打开,或者没有.
假设你有代码一个接一个地创建和返回一次性对象:
public IEnumerable<FileStream> GetFiles()
{
yield return File.OpenRead("file1");
yield return File.OpenRead("file2"); // does not exist
yield return File.OpenRead("file3");
}
Run Code Online (Sandbox Code Playgroud)
您需要获取所有一次性对象,但如果在获取过程中存在异常,那么已经产生的对象将保留在内存中而不会被丢弃.因此,Acquire要么获取所有流并返回它们,要么在失败时,它处理所有已获取的流并重新抛出异常.
FileStream[] streams = GetFiles().Acquire();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1493 次 |
| 最近记录: |