gpt4 book ai didi

c# - 使用 IDisposable 检查约束——疯狂还是天才?

转载 作者:太空狗 更新时间:2023-10-29 20:53:26 24 4
gpt4 key购买 nike

我在今天处理的代码库中遇到了一个模式,最初看起来非常聪明,后来让我发疯,现在我想知道是否有一种方法可以在最大限度地减少疯狂的同时挽救聪明的部分。

我们有一堆实现 IContractObject 的对象,以及一个看起来像这样的 InvariantChecker 类:

internal class InvariantChecker : IDisposable
{
private IContractObject obj;

public InvariantChecker(IContractObject obj)
{
this.obj = obj;
}

public void Dispose()
{
if (!obj.CheckInvariants())
{
throw new ContractViolatedException();
}
}
}

internal class Foo : IContractObject
{
private int DoWork()
{
using (new InvariantChecker(this))
{
// do some stuff
}
// when the Dispose() method is called here, we'll throw if the work we
// did invalidated our state somehow
}
}

这用于提供相对轻松的状态一致性运行时验证。这不是我写的,但最初看起来是个很酷的主意。

但是,如果 Foo.DoWork 抛出异常,问题就会出现。当异常被抛出时,我们很可能处于不一致状态,这意味着 InvariantChecker 也会抛出,隐藏原始异常。这可能会发生多次,因为异常会向上传播到调用堆栈,每帧都有一个 InvariantChecker 将异常隐藏在下面的帧中。为了诊断问题,我必须禁用 InvariantChecker 中的 throw,然后才能看到原始异常。

这显然很糟糕。但是,有没有什么办法可以挽救原始想法的聪明之处,而不会出现可怕的异常隐藏行为

最佳答案

我不喜欢重载 using 的意思的想法这样。为什么不用采用委托(delegate)类型的静态方法呢?所以你会写:

InvariantChecker.Check(this, () =>
{
// do some stuff
});

或者更好的是,将其作为扩展方法:

this.CheckInvariantActions(() =>
{
// do some stuff
});

(请注意,需要“this”部分才能让 C# 编译器查找适用于 this 的扩展方法。)这也允许您使用“正常”方法来实现操作,如果需要,并使用方法组转换为其创建委托(delegate)。如果您有时想从正文中返回,您可能还希望允许它返回一个值。

现在 CheckInvariantActions 可以使用类似的东西:

action();
if (!target.CheckInvariants())
{
throw new ContractViolatedException();
}

我还建议 CheckInvariants应该直接抛出异常,而不是仅仅返回 bool - 这样异常就可以提供有关哪个不变量被违反的信息。

关于c# - 使用 IDisposable 检查约束——疯狂还是天才?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5222379/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com