异常处理——这是好的做法吗?
Exception Handling - is this good practice?
我想知道我要做的是好事还是坏事。我有 class:
public class Element : IElement
{
public float? Max { get; private set; }
public float? Min { get; private set; }
public float? Average { get; private set; }
public bool HasValue { get; private set; }
public void SetRange(float? min, float? max)
{
if (min >= max)
{
throw new WrongElementValueException("Min must be greater than max!");
}
else if (min < 0f || max < 0f)
{
throw new WrongElementValueException("Min/max must be greater than 0!");
}
else if (min > 100f || max > 100f)
{
throw new WrongElementValueException("Min/max must be lesser than 0!");
}
else
{
Min = min;
Max = max;
Average = (min + max)/2f;
HasValue = true;
}
}
}
用户将使用 SetRange() 方法设置值。但他有一些限制,比如 Min 必须大于 Max,并且两者都不能大于 100 或小于 0。
我应该在这个地方使用那些例外吗?还是有更好的方法来处理错误的用户输入?
我希望我的问题不是笼统的。
只要无法实现有效的程序流(例如与数据库的连接丢失),异常就会很有用。因此,验证用户输入并在值无效时抛出异常是绝对可以的,而您也可以使用现成的建议 ArgumentException
。
这是一种适当的做法,是的。
虽然我想消费代码会期待 ArgumentException
而不是这种异常类型,但这可能是一个相对次要的问题。
当输入无效,并且对象无法以其他方式有意义地继续时,抛出异常是一种适当的预期响应。正确使用对象、处理错误、向用户报告等都取决于使用代码。
此对象的替代方案是 "try to figure out what to do",这通常会导致一些非常糟糕的编码做法。例如...
- 假设您想要 return 错误消息而不是抛出异常。如果使用代码不检查该错误消息怎么办?该对象将处于未知和无效状态,并可能悄悄地引入错误。而如果使用代码不检查异常,那么程序显然会失败,并且需要进行适当的更正。明显和明显的失败 比微妙和不被注意的失败更容易 支持。
- 假设您想要 "show a message to the user"。这将需要将此对象紧密耦合到表示层,这违背了面向对象的原则并使代码非常僵硬且难以维护。
这个对象做一件事,而且只做那一件事。如果它的调用方式使其不能做那件事,则异常是预期的且适当的失败条件。
如果您正确地抛出和捕获异常,那么在程序中处理异常是一种很好的做法。但在这里这是微不足道的事情,不需要抛出和反对,因为你可以通过简单的控制台打印来限制它。
在这种情况下两者的工作方式相同。
当有许多内部函数调用并且您当时不知道哪个会导致异常时,抛出异常会非常有用。
顺便说一下,你不认为这些是错误的。
如果(最小 >= 最大)
throw new WrongElementValueException("Min must be greater than max!");// 你正在打印的最小值应该大于最大值并且你正在检查相同值。
else if (min < 0f || max < 0f)
throw new WrongElementValueException("Min/max must be greater than 0!");
else if (min > 100f || max > 100f)
throw new WrongElementValueException("Min/max must be lesser than 0!");
我注意到已经有 ArgumentOutOfRangeException
正是为这种情况定义的。
if (min >= max)
throw new WrongElementValueException("Min must be greater than max!");
这绝对应该是一个 ArgumentException
,但是如果 WrongElementValueException
继承自 ArgumentException
,那就没问题了。
您的总体方法是合理的。我会考虑更进一步:
HasValue = true;
为什么允许 class 永远没有价值。考虑是否添加:
public Element(float min, float max)
{
SetRange(min, max);
}
现在您永远无法拥有一个没有设置值的实例,并且可以完全摆脱 HasValue
。
请注意,我将其从 float?
更改为 float
。您可能会被建议在整个 class 期间都这样做。否则,如果您需要 Min
和 Max
为空的情况(因此不想摆脱 HasValue
),您需要在 SetRange
:
public void SetRange(float? min, float? max)
{
if (min < 0f || max < 0f || min > 100f || max > 100f)
throw new ArgumentOutOfRangeException();
if (min >= max)
throw new WrongElementValueException("Min must be greater than max!");
Min = min;
Max = max;
if(min.HasValue && max.HasValue)
{
Average = (min + max)/2f;
HasValue = true;
}
else
{
Average = null;
HasValue = false;
}
}
(我通常更喜欢 double
和 double?
而不是 float
和 float?
,除非你有充分的理由。
顺便说一句,我们通常使用 "exception handling" 来讨论使用此代码的代码如何处理您的代码抛出异常这一事实,而最好的做法取决于该代码的上下文代码而不是此代码。
我想知道我要做的是好事还是坏事。我有 class:
public class Element : IElement
{
public float? Max { get; private set; }
public float? Min { get; private set; }
public float? Average { get; private set; }
public bool HasValue { get; private set; }
public void SetRange(float? min, float? max)
{
if (min >= max)
{
throw new WrongElementValueException("Min must be greater than max!");
}
else if (min < 0f || max < 0f)
{
throw new WrongElementValueException("Min/max must be greater than 0!");
}
else if (min > 100f || max > 100f)
{
throw new WrongElementValueException("Min/max must be lesser than 0!");
}
else
{
Min = min;
Max = max;
Average = (min + max)/2f;
HasValue = true;
}
}
}
用户将使用 SetRange() 方法设置值。但他有一些限制,比如 Min 必须大于 Max,并且两者都不能大于 100 或小于 0。
我应该在这个地方使用那些例外吗?还是有更好的方法来处理错误的用户输入? 我希望我的问题不是笼统的。
只要无法实现有效的程序流(例如与数据库的连接丢失),异常就会很有用。因此,验证用户输入并在值无效时抛出异常是绝对可以的,而您也可以使用现成的建议 ArgumentException
。
这是一种适当的做法,是的。
虽然我想消费代码会期待 ArgumentException
而不是这种异常类型,但这可能是一个相对次要的问题。
当输入无效,并且对象无法以其他方式有意义地继续时,抛出异常是一种适当的预期响应。正确使用对象、处理错误、向用户报告等都取决于使用代码。
此对象的替代方案是 "try to figure out what to do",这通常会导致一些非常糟糕的编码做法。例如...
- 假设您想要 return 错误消息而不是抛出异常。如果使用代码不检查该错误消息怎么办?该对象将处于未知和无效状态,并可能悄悄地引入错误。而如果使用代码不检查异常,那么程序显然会失败,并且需要进行适当的更正。明显和明显的失败 比微妙和不被注意的失败更容易 支持。
- 假设您想要 "show a message to the user"。这将需要将此对象紧密耦合到表示层,这违背了面向对象的原则并使代码非常僵硬且难以维护。
这个对象做一件事,而且只做那一件事。如果它的调用方式使其不能做那件事,则异常是预期的且适当的失败条件。
如果您正确地抛出和捕获异常,那么在程序中处理异常是一种很好的做法。但在这里这是微不足道的事情,不需要抛出和反对,因为你可以通过简单的控制台打印来限制它。
在这种情况下两者的工作方式相同。
当有许多内部函数调用并且您当时不知道哪个会导致异常时,抛出异常会非常有用。
顺便说一下,你不认为这些是错误的。
如果(最小 >= 最大) throw new WrongElementValueException("Min must be greater than max!");// 你正在打印的最小值应该大于最大值并且你正在检查相同值。
else if (min < 0f || max < 0f)
throw new WrongElementValueException("Min/max must be greater than 0!");
else if (min > 100f || max > 100f)
throw new WrongElementValueException("Min/max must be lesser than 0!");
我注意到已经有 ArgumentOutOfRangeException
正是为这种情况定义的。
if (min >= max)
throw new WrongElementValueException("Min must be greater than max!");
这绝对应该是一个 ArgumentException
,但是如果 WrongElementValueException
继承自 ArgumentException
,那就没问题了。
您的总体方法是合理的。我会考虑更进一步:
HasValue = true;
为什么允许 class 永远没有价值。考虑是否添加:
public Element(float min, float max)
{
SetRange(min, max);
}
现在您永远无法拥有一个没有设置值的实例,并且可以完全摆脱 HasValue
。
请注意,我将其从 float?
更改为 float
。您可能会被建议在整个 class 期间都这样做。否则,如果您需要 Min
和 Max
为空的情况(因此不想摆脱 HasValue
),您需要在 SetRange
:
public void SetRange(float? min, float? max)
{
if (min < 0f || max < 0f || min > 100f || max > 100f)
throw new ArgumentOutOfRangeException();
if (min >= max)
throw new WrongElementValueException("Min must be greater than max!");
Min = min;
Max = max;
if(min.HasValue && max.HasValue)
{
Average = (min + max)/2f;
HasValue = true;
}
else
{
Average = null;
HasValue = false;
}
}
(我通常更喜欢 double
和 double?
而不是 float
和 float?
,除非你有充分的理由。
顺便说一句,我们通常使用 "exception handling" 来讨论使用此代码的代码如何处理您的代码抛出异常这一事实,而最好的做法取决于该代码的上下文代码而不是此代码。