首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >还可以返回异常吗?

还可以返回异常吗?
EN

Stack Overflow用户
提问于 2011-10-10 22:07:32
回答 6查看 1.6K关注 0票数 2

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

代码语言:javascript
复制
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.
}

这是否还可以,还是被认为是“糟糕的做法”?

谢谢!

编辑

我阅读了不同的回复,看起来我做的完全错误。我试图使用上面的例子作为一个快速的例子,但看起来我应该只是张贴从入门的全部细节。下面是一个关于我的情况的更详细的例子:

代码语言:javascript
复制
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().

这是我的逻辑如果..。

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

在GetXEncoder()中抛出新异常、在GetCurrentCoords()中捕获和重新抛出新异常、在MoveToCoords()中捕获和重新抛出新异常、在GetHeightAtCoords()中捕获并在状态栏中显示消息(message = "Error in GetHeightAtCoords():Error in MoveToCoords():Error in GetCurrentCoords():Read X Value Error-6: status Error")。

由于GetXEncoder()可以从方法中的多个位置调用,所以我认为,如果让原始的异常气泡一直向上,对用户没有多大帮助。“GetHeightAtCoords()中的错误:读取X值错误-6:状态错误”,哪一次?)。以这个例子为例,哪个读取X值失败?GetHeightAtCoords() -> MoveToCoords() -> GetCurrentCoords() -> GetXEncoderValue()或GetHeightAtCoords() -> GetCurrentCoords() -> GetXEncoderValue()?

希望这一点更清楚:

这样的事做过吗?你建议我怎么做?再次感谢大家的意见!

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2011-10-10 22:48:33

创建一个总是抛出异常的方法有点难闻。看起来,这会处理错误,然后继续。我宁愿这样做:

代码语言:javascript
复制
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)); 
}

这非常清楚地表明,if (isError)结果总是抛出;在您的原始版本中,很难看出它会这样做。

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

在您的代码中还有更多的错误实践。

  • 不抛出new Exception;定义自己的异常类并抛出它。这样,调用方就可以捕获您的异常specifically.
  • Do,而不是捕获每个异常,然后将其包装到一个新的异常中并抛出。这到底有什么意义?如果每种方法都这么做呢?很快,您就会有一个包含了20多个级别的异常,并且无法计算出异常的真正含义。
  • 不会捕捉每个异常,然后显示一个消息框。首先,将错误处理机制代码与用户界面代码相结合,将两者分开。第二,您可能在这里报告各种异常--线程中止,内存不足等等。捕获一个特定的异常并处理它;如果您不知道如何从它恢复,不要吃it.
票数 11
EN

Stack Overflow用户

发布于 2011-10-10 22:11:22

这是不好的,因为您隐藏了异常的类型:

代码语言:javascript
复制
catch (Exception ex)
{
    throw new Exception("Error in SensorValue()", ex);
}

最好是简单地省略try { ... } catch { ... }。只有捕获异常,您可以做一些有用的事情。

这很糟糕,因为您正在捕获所有内容,但没有显示实际错误是什么:

代码语言:javascript
复制
catch (Exception ex)
{
    MessageBox.Show("Error in AverageSensorValues()");
}

您可能已经捕获了一个OutOfMemoryException、一个NullReferenceException或其他什么东西。你的用户不会知道。至少显示异常消息。

代码语言:javascript
复制
throw new Exception(String.Format("Error-{0}: See ...", errorNumber));

这是对异常的合理使用--将错误代码更改为异常。但是,您可能应该使用比Exception更具体的类型--甚至可能是从Exception派生的自定义类。

票数 1
EN

Stack Overflow用户

发布于 2011-10-10 22:15:54

没有必要使用这样的异常,异常应该是发生意外事件时的异常。它们不应成为一般控制流程的一部分。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7719241

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档