我有阅读各种传感器和处理数据的方法。在这些方法中,我有其他方法通过串口向电路发送命令(获取传感器值)。可能会发生通信错误,我想知道是否可以“返回”异常?例如:
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.
}
这是好的还是被认为是“不良做法”?
谢谢!
修改
好的,我阅读了各种各样的回复,看起来我完全错了(与我裸露,我是机械。)。我尝试使用上面的例子作为一个简单的例子,但看起来我应该刚刚从一开始就发布了完整的细节。所以这是我的情况的更详细的例子:
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() - &gt; MoveToCoords() - &gt; GetCurrentCoords() - &gt; GetXEncoderValue(),控制器响应错误。
在GetXEncoder()中抛出新的Exception,捕获GetCurrentCoords()并重新抛出新的Exception,捕获MoveToCoords()并重新抛出新的Exception,捕获GetHeightAtCoords()并在状态栏中显示消息(message =“ GetHeightAtCoords()中的错误:MoveToCoords()中的错误:GetCurrentCoords()中的错误:读取X值错误-6:状态错误“)。
因为可以从一个方法中的多个地方调用GetXEncoder(),我想如果我让原始的异常气泡一直向上,那对用户来说就没有什么帮助(例如“GetHeightAtCoords()中的错误:读取X值错误-6:状态错误“,哪个时间?)。举个例子,Read X Value失败了吗? GetHeightAtCoords() - &gt; MoveToCoords() - &gt; GetCurrentCoords() - &gt; GetXEncoderValue()或GetHeightAtCoords() - &gt; GetCurrentCoords() - &gt; GetXEncoderValue()?
希望更清楚:/
有这样的事吗?你会怎么推荐我继续?再次感谢大家的意见!
答案 0 :(得分: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));
}
这清楚地表明if (isError)
后果总是抛出;在你的原始版本中,很难看出它是这样做的。
此外,异常的堆栈跟踪设置在 thrown 的位置,因此这会将堆栈跟踪设置为检测到错误的点,而不是异常的位置构建,似乎更好。
您的代码中有许多不良做法。
不要抛出new Exception
;定义自己的异常类并抛出它。这样调用者可以专门捕获您的异常。
不要捕获每个异常,然后将其包装在新的异常中并抛出它。到底是什么意思呢?如果每个方法都这样做怎么办?很快你就会有一个异常包含二十几个级别,并且无法解决异常的真正含义。
不要捕获每个异常,然后显示一个消息框。首先,将错误处理机制代码与用户界面代码相结合;把这两个分开。其次,你可能会在这里报告所有类型的异常 - 线程中止和内存不足等等。捕获特定的异常并处理它; 如果您不知道如何从中恢复,请不要吃它。
答案 1 :(得分:1)
这很糟糕,因为你隐藏了异常的类型:
catch (Exception ex)
{
throw new Exception("Error in SensorValue()", ex);
}
最好是省略try { ... } catch { ... }
。只捕捉你可以做一些有用的异常。
这很糟糕,因为你正在捕捉所有内容,但没有显示实际错误:
catch (Exception ex)
{
MessageBox.Show("Error in AverageSensorValues()");
}
您可能完全抓住了OutOfMemoryException
,NullReferenceException
或其他内容。您的用户不会知道。在至少显示异常消息。
throw new Exception(String.Format("Error-{0}: See ...", errorNumber));
这是合理使用异常 - 将错误代码更改为异常。但您应该使用比Exception
更具体的类型 - 甚至可能是源自Exception
的自定义类。
答案 2 :(得分:1)
C#永远可以退回例外吗?
是的,但只有几个理由抛出异常。例如,如果执行符合永远不会发生的条件。
请看这里讨论when to throw an exception.
因为他们是正常发生的事情。例外不是 控制流动机制。用户经常会错误地输入密码,而不是密码 例外情况。例外应该是一个非常罕见的事情, UserHasDiedAtKeyboard类型情况
返回您的代码。
显示异常的实际消息更有意义。
catch (Exception ex)
{
MessageBox.Show(string.Format("Error in AverageSensorValues() - {0}", ex.Message));
}
下面的代码看起来不正确。返回您自己的错误(或结果)对象,而不是不必要地抛出异常。
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.
}
答案 3 :(得分:1)
使用类似的异常是没有意义的,异常应该是在发生意外情况时。它们不应该成为一般控制流程的一部分。
答案 4 :(得分:0)
如果唯一的原因是硬件故障 - 是的,可以抛出一个说'硬件故障'的例外。“
如果用户有错,你应该说'给我好的输入,再试一次。'。
答案 5 :(得分:0)
恕我直言,应该在导致程序不再运行或程序无法处理的情况下使用例外。
如果它是你可以恢复的东西,那么没有。
但是,您应该捕获任何异常并正确记录它们,以便您可以调试任何问题。