你会如何回答这个面试问题?
以下内容有什么危险?如何重写以使其更安全?
class Line
{public Point p1; public Point p2; public double length;}
谢谢,
答案 0 :(得分:3)
如果长度成员的意图是提供线的长度,则风险是可以改变长度而不考虑真实的线路长度。点之间的距离。
有很多方法可以解决这个问题。这是一个:
class Line {
public Point p1;
public Point p2;
public double length {
get {
return ....
}
}
}
这样,每次访问时都会计算距离,并且只读取该距离,因此可以防止引入不一致的更改
答案 1 :(得分:1)
首先,你没有在类上设置一个显式修饰符,所以你最终将会遇到默认情况(如果它在命名空间中,那么internal
或{{ 1}}如果包含在一个类中)。这可能会在编译时造成轻微的不便。更大的问题可能是默认情况下,类会使类超出预期范围,在这种情况下,您可能会无意中允许更多地访问类,而不是预期的类。无论如何,初学者或中等C#程序员很难看清楚这一点,知道会发生什么,这可能是一个可维护性问题。
但最大的问题是所有的课堂领域都被公之于众。通常,您希望使用属性来公开字段:限制读/写能力,通过反射使字段更容易被发现,执行验证等。这导致......
您可以看到该类名为“Line”,并显示它的点和它的长度。调用者当前可以轻松更改任何这些值,但其他值不会更新。长度应该是计算属性(只读),因为更改长度会产生不可预测的结果(哪个点会改变?)。
所以我会把这个类重写为:
private
如果有多个线程一起工作,或者即使在两个对象引用同一个Line实例并且一个对象可能不知道另一个更改(因此导致问题)的简单情况下,此类的可变性可能会导致问题)。如果可变性是一个问题,那么所有属性都应该是只读的:
public class Line
{
public Point P1 {get;set;}
public Point P2 {get;set;}
public double Length
{
get
{
return Math.Sqrt(
Math.Pow( P2.X - P1.X, 2 ) +
Math.Pow( P2.Y - P1.Y, 2 )
);
}
}
}
答案 2 :(得分:1)
所有成员都应该是属性getter / setter。支持成员/字段是可选的 例外是Length属性。您不希望长度修改独立于线特征 - 例如不考虑使该属性为只读的点坐标。
class Line {
private Point _startPoint;
private Point _endPoint;
public double Length {
get { return _startPoint.X - _endPoint.X; } // modify for your own algorithm
}
// add public property setters for Start and End Points
}
这可以防止最终开发人员或消费者应用程序独立于行坐标修改长度。
注意:
一条线似乎是一个值类型,可以是一个结构。