永远可以退回例外吗?

joh*_*ohn 2 .net c# exception

我有读取各种传感器和过程数据的方法.在这些方法中,我有其他方法通过串口向电路发送命令(获取传感器值).可能会发生通信错误,我想知道是否可以"返回"异常?例如:

public double AverageSensorValues()
{
  try
  {
   ...
   double sensor1Value = SensorValue(1);
   double sensor2Value = SensorValue(2);
   ...
   }
   catch (Exception ex)
   {
      MessageBox.Show("Error in AverageSensorValues()");
   }
}

public double SensorValue(int sensorNum)
{
   try {

   // Send command to circuit to return value.
   string response = SendCommand(commandStringToGetValue);

   // Check to see if response is an error
   bool isError = ErrorReturned(response);

   if(isError)
      ProcessError(response);  // Throws exception.

   ... // Other things that could cause exceptions to be thrown.

   }
   catch (Exception ex)
   {
      throw new Exception("Error in SensorValue()", ex);
   }
}

public void ProcessError(string errorResponse)
{
   // Split string and get error parameters (#, input command, etc.)

   throw new Exception(String.Format("Error-{0}: See ...", errorNumber));  // Is this OK? More readable than "ER,84,DM,3L" for example.
}
Run Code Online (Sandbox Code Playgroud)

这是好的还是被认为是"不良做法"?

谢谢!

编辑

好吧,我阅读了各种各样的回复,看起来我完全错了(与我一起,我是一个mech.eng.).我尝试使用上面的例子作为一个简单的例子,但看起来我应该刚刚从一开始就发布了完整的细节.所以这是我的情况的更详细的例子:

public double[] GetHeightAtCoords(CoordClass[] coords)  // Get height measurement at various positions. Called after button click, results are displayed on UI.
{
   try  // Error could occur within one of these methods. If it does, not Program critical but it should notify user and not return any result.
   {
   for(int coordIndex = 0; coordIndex < coords.Length; coordIndex++)  // Cycle through each desired position.
   {
      ...
      currentCoords = GetCurrentCoords();   // Get current actuator position.
      ... //Update UI.
      MoveToCoords(coords[coordIndex]);   // Move actuator to position.
      currentCoords = GetCurrentCoords(); // Verify position.
      EngageBrake();   // Lock actuator in place.
      double height = GetHeight(); // Read sensor data.
      ReleaseBrake();   // Release brake.
      ...
   }
  }
  catch (Exception ex)
  {
     // Display in statusbar.
     statusBar1.Text = String.Format("Error in GetHeightAtCoords(): {0}", ex.Message);
  }

   ...
   return heights;  // Return position heights array.
}

public CoordClass GetCurrentCoords()   // Method to read positional encoder values.
{
   ...
   try
   {
   double xPosition = GetXEncoderValue();   // Return x-coord value.
   double yPosition = GetYEncoderValue();   // Return y-coord value.
   }
   catch (Exception ex)
   {
      throw new Exception("Error in GetCurrentCoords(): {0}", ex.Message);
   }
   ...
   return new CoordClass(xPosition, yPosition); // Return current coords.
}

public void MoveToCoords(CoordClass coord)   // Method to move actuators to desired positions.
{
   try
   {
   ... 
   currentCoords = GetCurrentCoords(); // See where actuators are now.
   ... // Setup movement parameters.
   MoveToX(coord.X);   // Move x-axis actuator to position.
   MoveToY(coord.Y);   // Move y-axis actuator to position.
   }
   catch (Exception ex)
   {
      throw new Exception("Error in MoveToCoords(): {0}", ex.Message);
   }
   ...
}

public double GetXEncoderValue()   // Method to return x-coord value.
{
   string getXCoordCommand = "SR,ML,01,1";   // Serial command to get x-coord.
   ...
   string controllerResponse = SendReceive(getXCoordCommand);  // Send command, get response command.

   if(!ResponseOK(controllerResponse))   // If the response doesn't match the "command OK" response (i.e. SR,ML,01,1,OK)...
   {
      if(IsErrorResponse(controllerResponse))  // See if response is an error response (e.g. command error, status error, parameter count error, etc.)
         // Some known error type occurred, cannot continue. Format error string (e.g. ER,SRML,61) to something more meaningful and report to user (e.g. Read X Value Error: Status error.).
         throw new Exception("Read X Value Error-{0}: {1}", errorNumber, (ErrorEnum)errorNumber);
      else
         // Something else went wrong, cannot continue. Report generic error (Read X Value Error.).
         throw new Exception("Read X Value Error.");
   }
   ...
}

// GetYEncoderValue(), MoveToX(), MoveToY(), GetHeight(), EngageBrake() and ReleaseBrake() follow the same format as EngageBrake().
Run Code Online (Sandbox Code Playgroud)

这是我的逻辑,如果......

调用顺序:GetHeightAtCoords() - > MoveToCoords() - > GetCurrentCoords() - > GetXEncoderValue(),控制器响应错误.

在GetXEncoder()中抛出新的Exception,捕获GetCurrentCoords()并重新抛出新的Exception,捕获MoveToCoords()并重新抛出新的Exception,捕获GetHeightAtCoords()并在状态栏中显示消息(message ="GetHeightAtCoords中的错误():MoveToCoords()中的错误:GetCurrentCoords()中的错误:读取X值错误-6:状态错误").

因为GetXEncoder()可以从一个方法中的多个地方调用,所以我想如果我让原始异常气泡一直向上,那对用户来说就没有什么帮助(例如"GetHeightAtCoords()中的错误:读取X值错误-6:状态错误",哪个时间?).举个例子,Read X Value失败了吗?GetHeightAtCoords() - > MoveToCoords() - > GetCurrentCoords() - > GetXEncoderValue()或GetHeightAtCoords() - > GetCurrentCoords() - > GetXEncoderValue()?

希望更清楚:/

有这样的事情吗?你会怎么推荐我继续?再次感谢大家的意见!

Eri*_*ert 11

制作一个总是抛出异常的方法有点难闻.它看起来像处理错误然后继续.我宁愿这样做:

if(isError)
      throw MakeMeAnException(response);  
...
}

public Exception MakeMeAnException(string errorResponse)
{
   // Split string and get error parameters (#, input command, etc.)
   return new MyException(String.Format("Error-{0}: See ...", errorNumber)); 
}
Run Code Online (Sandbox Code Playgroud)

这很清楚,if (isError)结果总是抛出; 在你的原始版本中很难看到它做到了.

此外,异常的堆栈跟踪设置在它被抛出的位置,因此这将堆栈跟踪设置为检测到错误的点,而不是构造异常的点,这似乎更好.

你的代码中有很多不好的做法.

  • 不要扔一个new Exception; 定义自己的异常类并抛出它.这样调用者可以专门捕获您的异常.

  • 不要捕获每个异常,然后将其包装在新的异常中并抛出它.到底是什么意思呢?如果每种方法都这样做怎么办?很快你就会有一个异常包含二十多个级别,并且无法解决异常的真正含义.

  • 不要捕获每个异常,然后显示一个消息框.首先,将错误处理机制代码与用户界面代码相结合; 把这两个分开.其次,你可能会在这里报告所有类型的异常 - 线程中止和内存不足等等.抓住一个特定的例外并处理它; 如果你不知道如何从中恢复,不要吃它.