C# 如何在使用代码契约时记录错误

C# 如何在使用代码契约时记录错误,c#,.net,code-contracts,C#,.net,Code Contracts,我需要在我的应用程序中记录异常(即使是在发布版本中)。 我使用类CLog的静态方法Log(Exception ex)来记录异常。 我还使用代码契约,并同时使用静态和运行时检查。 请考虑以下代码: public void editCommit(CEmployee emp) { Contract.Requires<ArgumentNullException>(null != emp, "Null argument, Parameter name : emp");

我需要在我的应用程序中记录异常(即使是在发布版本中)。 我使用类
CLog
的静态方法Log(Exception ex)来记录异常。 我还使用代码契约,并同时使用静态和运行时检查。 请考虑以下代码:

public void editCommit(CEmployee emp)
    {
        Contract.Requires<ArgumentNullException>(null != emp, "Null argument, Parameter name : emp");
        this.employee.Name = emp.Name;
        this.employee.Age = emp.Age;
    }
public void editCommit(CEmployee emp)
{
Requires(null!=emp,“null参数,参数名称:emp”);
this.employee.Name=emp.Name;
this.employee.Age=emp.Age;
}
现在,如果我没有更正生成的所有警告,我如何记录运行时抛出的异常
ArgumentNullException
?我需要用相同的方法记录异常。
请帮助。

捕获调用/任何上层函数中的异常

编辑:示例

public void editCommit(CEmployee emp)
    {
        try
        {
           Contract.Requires<ArgumentNullException>(null != emp, "Null argument, Parameter name : emp");
           this.employee.Name = emp.Name;
           this.employee.Age = emp.Age;
         }
         catch( ArgumentNullException x )
         {
             System.Console.Error.WriteLine( "{0}: {1} @", typeof( x ).Name, x.Message );
             System.Console.Error.WriteLine( "{0}", x.StackTrace };
             //now throw the exception again so the caller can react to the error
             throw;
         }
    }
public void editCommit(CEmployee emp)
{
尝试
{
Requires(null!=emp,“null参数,参数名称:emp”);
this.employee.Name=emp.Name;
this.employee.Age=emp.Age;
}
捕获(异常x)
{
System.Console.Error.WriteLine(“{0}:{1}@”,typeof(x.Name,x.Message);
System.Console.Error.WriteLine(“{0}”,x.StackTrace};
//现在再次抛出异常,以便调用方能够对错误作出反应
投掷;
}
}
当然,您可以使用任何其他库来记录错误,我更喜欢log4net。
如果您编写交互式程序,请不要忘记通知用户操作失败:-)

契约异常的处理方式应与普通异常不同,因为契约应指定与您的程序相关的事实,无论系统的状态如何,该事实应始终为真。如果合同失败,这意味着您的代码中几乎肯定有一个bug。代码契约团队提供了另一种发现故障的方法,这种方法在这种情况下可能很有用(请参阅手册第7节“运行时契约行为”)

您有两个选项:您可以为ContractFailedEvent提供事件处理程序(这是我在本例中建议的),或者为ContractRuntime类提供完整的替换(有关此类的更多详细信息,请参阅手册)

应尽早注册事件处理程序:

static void Main(string[] args)
{
    InitialiseContractHandler();
    //...
}

public static void InitialiseContractHandler()
{
    Contract.ContractFailed += (sender, eventArgs) =>
    {
        eventArgs.SetHandled();
        eventArgs.SetUnwind();                  
        MyContractFailureLogger(eventArgs);
        Assert.Fail(eventArgs.Message);
    };
}
我使用此模式的原因是,您还可以从AssemblyInitializer方法调用Initializing方法以进行单元测试


以这种方式设置失败将防止契约运行时本身抛出异常,这就是为什么我包含了Assert.Fail()-毕竟,您仍然希望终止执行。

我实际上正在尝试找出是否有任何方法可以用相同的方法捕获异常。我还想知道记录异常的正确方法。我需要记录所有的异常,即使是在发布版本中。但我也热衷于使用代码契约来最小化bug。请建议如何将两者结合以获得最佳结果。上面的代码给出了以下错误“error:Contract section in try block”。@AnirbanPaul-我认为这是一个失败的原因。检测此故障的唯一方法是捕获异常。但是,正如您所看到的,合同必须是方法的第一部分。因此,您无法从同一方法中检测到此故障。抱歉,我不知道这一点,因为我通常不在同一函数中对其进行catc-至少不在代码契约例外情况下-为什么要求在同一方法中记录它?为什么不将它与所有其他未处理的异常一起收集到顶级异常处理程序中呢?我遵循MVVM体系结构开发WPF应用程序。您能建议我如何记录1>合同异常2>未处理的异常(在这种情况下,我们应该处理并登录DispatcherUnhandledException???)3>其他线程中的异常生成的错误吗?我不使用WPF,因此我无法帮您。如果您想知道处理未处理异常和跨线程异常的最佳实践,或者通常的“如何记录”(例如,日志框架),您应该单独提出这些问题。它们实际上与代码契约无关。