1

我希望我的对象不变方法抛出一个特定的异常。是否有意义?在 C# 中可能吗?

例如,我有以下代码,包括具有不变方法的类 A 和异常类 E。目前 E 类不参与 A ...

class A {
    int x = 0, y = 1;

    [ContractInvariantMethod]
    private void YisGreaterThanX() {
        Contract.Invariant(x < y);
    }
}

class E : Exception {
}

我需要的是以下内容。像 Contract.Requires 一样,拥有 Contract.Invariant (或者可能是一个属性构造函数,它接受异常派生类)会很有用。

class A {
    int x = 0, y = 1;

    [ContractInvariantMethod]
    private void YisGreaterThanX() {
        Contract.Invariant<E>(x < y);
    }
}

class E : Exception {
}

是好意吗?可能是我的逻辑错了?

4

1 回答 1

0

鉴于我们不应该捕获 Contract failures,并且由于Contract.Invariant没有显式指定异常的重载,因此希望这个答案是假设性的。

因此,在所有免责声明之后,您可以通过连接ContractFailed事件处理程序来破解以下内容:

Contract.ContractFailed += Contract_ContractFailed();

在处理程序中,过滤Invariant失败,处理失败并重新抛出你的异常:

public static void Contract_ContractFailed(object sender,  ContractFailedEventArgs e)
{
    if (e.FailureKind == ContractFailureKind.Invariant)
    {
        e.SetHandled();
        throw new E(e.Message, e.OriginalException);
    }
}

鉴于您无法在Contract.Invariant定义中传递太多信息,如果您需要参数化抛出的异常,则需要将预期的异常编码为例如bool, string Contract.Invariant重载,或使用外部全局状态,例如线程本地存储。

所有这些都是臭的IMO。因此,要回答您的最后一个问题,我认为抛出可捕获的异常根本不是一个好主意-您的代码被调用超出其设计的状态范围,因此某处缺少错误/验证。

编辑
随后注意到,处理程序中的处理+投掷ContractFailed仍然包裹在内部ContractException。所以你需要打开包装,例如

catch(Exception ex)
{
   var myException = ex.InnerException;
   // ... do something
}
于 2013-12-23T07:43:56.437 回答