Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 对何时抛出异常感到困惑_C#_.net_Exception Handling - Fatal编程技术网

C# 对何时抛出异常感到困惑

C# 对何时抛出异常感到困惑,c#,.net,exception-handling,C#,.net,Exception Handling,我正在开发一个库,该库设计用于与外部设备通信(通过RS232串行通信)。我在考虑错误处理策略,异常似乎是正确的,并且是报告错误的行业标准方法 所以我很少阅读关于例外情况的指南。非常明确地指出,我应该而不是担心性能问题: 不要使用错误代码,因为担心异常可能会对性能产生负面影响 告诉我在正常情况下不要抛出异常: 不要将异常用于正常或预期错误,或用于正常控制流 我无法在正常/预期和其他情况之间划清界限。例如,在我的库中,操作可能会失败,因为: 设备没有响应。(未连接电缆,设备未打开,波特率错误) 操作

我正在开发一个库,该库设计用于与外部设备通信(通过RS232串行通信)。我在考虑错误处理策略,异常似乎是正确的,并且是报告错误的行业标准方法

所以我很少阅读关于例外情况的指南。非常明确地指出,我应该而不是担心性能问题:

不要使用错误代码,因为担心异常可能会对性能产生负面影响

告诉我在正常情况下不要抛出异常:

不要将异常用于正常或预期错误,或用于正常控制流

我无法在正常/预期和其他情况之间划清界限。例如,在我的库中,操作可能会失败,因为:

  • 设备没有响应。(未连接电缆,设备未打开,波特率错误)
  • 操作请求被设备拒绝,因为它无法对请求进行身份验证
  • 两者之间的通信失败。(有人被电缆绊倒,设备突然断电)
  • 我可以认为以上所有问题都是意料之中的问题,因为它们在实践中经常发生(事实上,许多营销白痴打电话给我解决软件中的问题,却发现他们没有将电缆连接到笔记本电脑)。因此,可能不应该抛出异常,因为否则应用程序程序员将不得不在很多地方捕捉这些异常(我相信,有很多捕捉块也不好)

    另一方面,我也倾向于认为这些都是我需要以某种方式向应用程序程序员报告的错误,而异常似乎就是这样做的方法。如果我不使用异常,我将需要使用一些错误代码或错误枚举来报告这些问题。(丑,我知道)


    您认为我应该采用哪种方法?

    使用RS232,除非您启用了硬件握手功能(大多数情况下,人们都没有),否则您将看不到更多的数据从线路中输入。除了没有向PC发送任何信息之外,您无法判断设备是否已连接

    我可能会将1和3一起归类为RS232TimeoutError,将2归类为RS232AuthenticationError

    一般来说,TimeoutError表示远程设备已锁定或未连接。身份验证错误有点像协议错误,但微妙的区别在于通信正常,但远程设备“只是拒绝”与PC建立连接

    我认为将这些设置为异常是合理的:在正常操作期间,您永远不会期望出现超时错误,也不会期望出现身份验证错误。

    您正在开发一个库,一个将由其他应用程序使用的组件

    因此,在您提到的预期情况下,我肯定会使用异常来与调用应用程序进行通信,指出有问题。您应该为这些场景中的每一个定义一个自定义异常,然后清楚地记录它们可能发生的时间

    然后,这允许应用程序客户机代码决定如何最好地继续。只有客户机应用程序才能做出此决定,并且清楚地记录异常会大大有助于这一点

    自定义异常最好的一点是,您可以提供与问题/异常相关的多个有意义/有用的数据段。这些数据也很好地封装在一个对象中。将其与错误代码和返回值进行比较

    性能可能是一个问题,但只有在紧循环或其他高活动性情况下引发异常时才会出现。为了避免这种情况,您还可以应用.NET Framework使用的模式,即提供Try….()方法(例如
    TryParse()
    ),该方法返回布尔值,指示操作是成功还是失败


    无论哪种方式,我都会先使用自定义异常,然后进行性能测试,以实际查看库中是否有某些部分需要优化。

    是否引发异常是函数类型的结果

    • 如果函数返回一个X,而您无法确定一个有效的X,则抛出一个异常
    • 如果函数是一个操作(如Connect),而您未能完成该操作,则引发异常
    • 如果函数是TryX类型,则不要抛出异常

    所以我想我是说你应该把问题从“我应该抛出一个异常吗?”推到“调用我的库的人想要什么方法?”并警告说,根据你提供的方法,你抛出的异常应该是明显的(灵感来自合同设计)

    • 如果可能,请提供布尔值 检验职能部门告诉你 手术是否能安全进行 应用
    • 对于给定的操作,考虑 这样一种检查功能,如 前提条件:如果成立,则 操作可以安全完成,如果不能,您可以 抛出异常
    通过这种方式,如果API用户可以使用if-then-else结构对其密钥逻辑进行编码

    如果出现意外情况(例如,由于微妙的时间问题),将引发异常:开发人员可以捕获此异常并处理它。但是注意:这不需要在调用方法的位置:它可以在调用堆栈中更高/更早的位置,在处理所有奇怪异常的中心位置

    我在数百万行C程序中的错误处理代码的自动分析方面做了一些工作。这些代码是基于要求手写检查和错误代码传播的编码标准。事实证明,开发人员不喜欢编写这样的代码,他们忘记了,而且很容易出错。事实上,我们发现了两个每1000行C代码中的编码标准(有人可能会说有2个错误)

    • 见M.Bruntink,A.van Deur
      Public Function Nz(ByVal value As String, ByVal valueIfNothing As String) As String
          Try
              Dim sValue As String = System.Convert.ToString(value) 'using Convert.ToString on purpose
              If IsNothing(sValue) Then
                  Return valueIfNothing 
              Else
                  Return sValue
              End If
          Catch ex As Exception
              'Convert.ToString handles exceptions, but just in case...
              Debug.Fail("Nz() failed. Convert.ToString threw exception.")
              Return String.Empty
          End Try
      End Function
      
      Public Function Nz(ByVal value As String, ByVal valueIfNothing As String) As String
          Dim sResult As String = String.Empty
          Dim sValue As String = System.Convert.ToString(value) 'using Convert.ToString on purpose
          If IsNothing(sValue) Then
              sResult = valueIfNothing 
          Else
              sResult = sValue
          End If
          Return sResult
      End Function