假设我有一个类Point
class Point
{
public double? x, y;
}为了表明x或y是未知的,我将它们的类型设为可空。
现在,当在数学表达式中使用这些值时,每次都必须将它们的值强制转换为双倍,这是不方便的。也就是说,Math.Sin(p.x)将产生编译时错误;您必须改为强制转换它:Math.Sin((double)p.x)。
我解决强制转换问题的方法是让包装器只读属性来执行强制转换:
class Point
{
public double? x, y;
public double X { get { if (x != null) return (double)x; else throw new Exception(); } }
public double Y { get { if (y != null) return (double)y; else throw new Exception(); } }
}这是一种好的方法吗?
发布于 2012-02-06 23:38:51
您可以使用Nullable的Value属性
Math.Sin(p.x.Value)或
public double X { get { return x.Value; } }如果没有设置该值,这将抛出异常,因此等同于您的代码。
关于这些方法的相对优点:
IMO,基于属性的方法屏蔽了消费者的实现细节,即x在内部存储为Nullable以表示未知性。如果期望消费者只处理“已知”值,这将是我的偏好。但是,如果期望消费者满足x仍然“未知”的情况,那么公开Nullable属性将是可行的(并且任何消费者都可以使用Nullable的HasValue属性进行检查)。
发布于 2012-02-06 23:58:14
就我个人而言,我不太喜欢在试图访问属性时抛出的通用异常(特别是当访问Nullable<T>的.Value时当HasValue == false时抛出的通用InvalidOperationException )。相反,我将公开指定是否定义这些值的布尔属性:
这将是开发人员在尝试访问属性之前检查成员有效性的合同的一部分:
public class Point
{
private double? x;
private double? y;
public bool IsXDefined { get { return this.x.HasValue; } }
public bool IsYDefined { get { return this.y.HasValue; } }
// Returns an undefined value (default(double)) in case X is not defined
// This is a part of the contract that X is valid if, and only if IsXDefined is true.
public double X { get { return x ?? default(double); } }
public double Y { get { return y ?? default(double); } }
}
Point p = new ...
if (p.IsXDefined)
{
double zz = p.X ....
}实际上,对于相同的目标,有不同的方法,但重要的是,开发人员知道代码实际做了什么。异常是一种很好的方式,可以让开发人员知道他试图读取的属性并不处于良好状态。
在上面的代码中,X属性的文档将显示“点的X坐标(如果已定义)。要确保X是有效值,请在尝试访问此属性之前检查IsXDefined是否返回true”。
PointCoordinateNotDefinedException也很棒:
public double X
{
get
{
if (this.IsXDefined)
{
return this.x.Value;
}
throw new PointCoordinateNotDefinedException();
}
}合同也是如此:X属性的文档会说“如果坐标没有定义,可以抛出PointCoordinateNotDefinedException异常。在尝试访问此属性之前,请检查IsXDefined是否返回true”。
这两个对我来说都是可以的,也许异常更好你是对的,因为如果值是未指定的,它将使应用程序崩溃(这将防止应用程序使用不正确的值运行(比查看堆栈跟踪来查看抛出异常的原因更难调试))。
但是,在抛出异常(同时捕获这些异常)之前,我不认为尝试访问属性是一个好主意。我更喜欢在访问属性之前测试IsXDefined布尔值。
https://stackoverflow.com/questions/9162613
复制相似问题