如果不使用异常,哪种技术是正确的
本文关键字:技术 异常 如果不 | 更新日期: 2023-09-27 18:11:27
假设我有一个这样的类
class A
{
private int _x; //must be between [-10 10]
private int _y; //must be between [10 20]
}
使用属性我有几个变量
的变体public int X
{
get { return _x; }
set
{
if (!(value >= -10 && value <= 10))
throw new Exception("Some error text");
_x = value;
}
}
或
public int X
{
get { return _x; }
set
{
if (!(value >= -10 && value <= 10))
return;
_x = value;
}
}
(与_y相同)。
在第一种情况下,我不确定我是否想使用异常(它们很慢,并且有其他已知的问题)。其次,我要为不使用值的模糊性而付出代价(以不同的方式使用_x和_y)。显然,在我的情况下(如果处理一个对象列表),我可以像这样使用smth
public bool IsValid = true;
//...
public int X
{
get { return _x; }
set
{
if (!(value >= -10 && value <= 10))
{
IsValid = false;
return;
}
_x = value;
}
}
class AWrapper
{
public List<A> AList {get; set;}
public AWrapper(List<A> list)
{
AList = list.Where(x => x.IsValid == true).ToList();
}
}
或者一些验证器类,我猜还有其他一些东西。所以我只是想为自己制定一个标准——哪种技术更好,什么时候……
让我们直接开始吧;异常可能"很慢",但这正是为什么只在特殊情况下使用它们的原因。
在你的例子中,如果一个超出给定范围的数字是异常的(即,不应该发生),那么你可以抛出一个异常。但是,如果这类似于用户输入,那么用户在可接受范围之外填写的值肯定是而不是异常!在这种情况下,您需要的是验证输入的值是否在可接受的范围内。
关于这个解决方案的另一点:
set
{
if (!(value >= -10 && value <= 10))
return;
_x = value;
}
在我看来,这同样糟糕(如果不是更糟的话)。原因是,如果我设置X=10
,我期望当我读取X
时,它具有我刚刚设置的值。
在这种情况下,常见的方法是引发InvalidArgumentException。如果你不想处理异常,你可以引入自定义标志IsValid
(正如你已经提到的)。
要持久保存属性范围,我建议为此引入自定义属性,并通过它标记属性,如:
public bool IsValid { }
[ValueRange(Max = 10, Min = 5)]
public int X
{
set
{
this.ValidateValueRange(this.X, value);
}
}
private bool ValidateValueRange(...)
{
// 1. Get property value (see link below regarding retrieving a property)
// 2. Get ValueRange attribute values
// 3. Update this.IsValid
// 4. Return ...
}
然后实现单一方法检查value
的传递是否在范围内
的有用链接:
- 创建自定义属性(c#编程指南)c#中如何使用Lambda表达式获取属性名
我试着给一些流程如何决定在这里使用:
如果你不希望出现频繁的"无效"情况,那么一定要使用异常。
set
{
if (!(value >= -10 && value <= 10))
throw new Exception("Some error text");
_x = value;
}
如果你需要最大的性能,如果它是可接受的,你可以记录你的setter,并声明所有超出范围的值都被忽略。
set
{
if (value >= -10 && value <= 10)
_x = value;
// else optionally log something
}
如果静默忽略不正确的值不是一个选项,添加日志记录或IsValid标志,就像你的例子一样。但是要注意,您将检测/检查问题的责任转移给了调用者。异常更好,因为你必须处理它们,否则你会直接受到惩罚。
使用另一个答案中呈现的自定义属性只是实现检查的另一种方式。
我希望这些提示对你有帮助。. net中检查值是否有效的标准模式是创建一个方法先检查值,让类的用户调用它,然后处理结果并抛出异常。
例如:public bool IsValueValid(xxx)
{
}
public void SetValue(xxx)
{
if(!this.IsValueValid())
{
throw Exception();
}
}
通常,必须存储该值的类不知道如何处理无效值,这是调用者的工作,知道如何处理该值
坚持
public int X
{
get { return _x; }
set
{
if (!(value >= -10 && value <= 10))
throw new Exception("Some error text");
_x = value;
}
}
如果您想验证从UI接收到的用户输入,那么我建议您使用Validator方法,其中您有能力通知用户期望的内容。
这是一种权衡,在其他情况下,您必须决定不显示异常的代价,并继续使用任何安全/默认值或使用自定义异常中断流。