我班上有这样的字段:
public class Shape
{
private Point2D m_location;
public void Move()
{
m_location = ...
}
public void Rotate()
{
m_location = ...
}
public void Flip()
{
m_location = ...
}
}
我在 NDepend 中收到警告:
不要从许多方法中分配字段
https://www.ndepend.com/default-rules/Q_Don't_assign_a_field_from_many_methods.html
我似乎可以通过在我的课程中创建另一种方法来轻松解决这个问题:
private void SetLocation(Point2D point)
{
m_location = location;
}
并在设置m_location
的所有方法中调用它。现在m_location
仅在一种方法中分配!
这是解决此问题的有效方法吗?我只是通过在这些方法中调用SetLocation()方法来隐藏之前检测到的代码气味NDepend吗?
答案 0 :(得分:2)
这是解决此问题的有效方法吗?
没有。如你所料,这是一种代码味道。 NDepend抱怨的是可变引用;你有代码在哪里:
var s = new SomeObject(someInitialization);
var r = s.SomeResult();
// you now have no idea what s contains or if it is even usable any more.
解决这个问题的方法是使SomeObject
不可变并返回新引用而不是更改内部:
public SomeObject Something()
{
return new SomeObject(SomethingDifferentDependingOn(this.something));
}
现在代替你的第一个例子:
var s = new SomeObject(someInitialization);
var r = s.Something().Result;
// s is guaranteed to be unchanged.
是的,有时您会需要可变引用。在那些情况下;记录它们并解释为什么它们必须是可变的。然后,您可以根据具体情况override NDepend rules来防止它显示警告。如果你有代码味,请警告人们。不要试图隐藏它。
编辑后的示例完全不同,但一般原则仍然有效。如果您只有几个内部字段在方法调用中都发生了变化,您仍然可以返回不可变引用,例如:
public Shape Move()
{
return new Shape(m_location ...);
}
如果您有许多内部字段不会全部更改,或者您需要执行类似共享私有字段的操作,则您无法轻松获得不可变引用,但您仍然可以通过使用访问器来避免警告:
public Location
{
get { return m_location; }
private set { m_location = value; }
}
然后在您的内部方法中使用Shape.Location
。