作者热门文章
- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我们的代码库中有以下构造,用于确保特定资源在使用后得到处理:
using (var disposableThing = DisposableThing.Begin())
{
// do something
disposableThing.Finish(); // must always be called
}
这是它的用法示例:
List<int> ids;
using (var disposableThing = DisposableThing.Begin())
{
ids = disposableThing.GetSomeIds();
disposableThing.Finish();
}
DoSomethingElseWith(ids);
由于这种模式很常见,我们在 DisposableThing
上写了一个方法封装它:
static void ExecuteWithFinish(Action<DisposableThing> action)
{
using (var disposableThing = Begin())
{
action(disposableThing);
disposableThing.Finish();
}
}
这允许我们将第二个示例重写为:
// #4
List<int> ids;
DisposableThing.ExecuteWithFinish(disposableThing =>
{
ids = disposableThing.GetSomeIds();
});
DoSomethingElseWith(ids); // compiler error "Use of unassigned local variable 'ids'"
但编译器拒绝编译该代码,因为它无法知道 ids
将始终在 ExecuteWithFinish
之后分配已完成(或抛出异常,无论如何都会阻止 DoSomethingElseWith
的执行)。
ExecuteWithFinish
的重载从传入的 Func
返回值, 这很丑。DisposableThing
并覆盖它的 Dispose
调用方法 Finish
,这是一种比每次都构造一个委托(delegate)更干净、更整洁、更快的方法(这可能是我最终会做的)。但为了我自己的启迪和“假设”的精神,是否有可能通知甚至欺骗编译器允许#4 中编写的代码?
编辑: 是的,我知道我可以写 List<int> ids = null;
并完全规避这个问题,但是 (a) 我不想执行不必要的分配 (b) 我想尽可能少地更改代码。
最佳答案
我会在这里采取不同的方法。
我将假设由于某种原因,您必须有一个必须始终在 Dispose()
之前调用的 Finish()
方法,该方法也必须总是被调用。
这可能是一个轻率的假设,它确实在回避问题:为什么不将 Finish()
的功能放入 Dispose()
中?然而……
首先,创建一个接口(interface),用 Finish()
方法封装一个一次性的东西:
public interface IDisposableThingWithFinish : IDisposable
{
void Finish();
}
并更改您的 DisposableThing
类,使其实现 IDisposableThingWithFinish
。
然后您可以编写一个封装调用 Finish()
和 Dispose()
的一次性类,如下所示:
public sealed class DisposingFinisher : IDisposable
{
readonly IDisposableThingWithFinish _item;
public Disposing(IDisposableThingWithFinish item)
{
if (item == null)
throw new ArgumentNullException(nameof(item));
_item = item;
}
public void Dispose()
{
try
{
_item.Finish();
}
finally
{
_item.Dispose();
}
}
}
您可以像这样使用 Finisher
:
using (var disposableThing = new DisposingFinisher(DisposableThing.Begin()))
{
// Do something.
}
关于c# - 有没有办法告诉编译器将始终执行特定代码块?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40889341/
我是一名优秀的程序员,十分优秀!