鉴于名为OrderInfo
的类,确保其他开发人员(包括我自己)不会意外地产生此处显示的递归错误的最佳方法是什么:
public class OrderInfo : ICollection<UnitModule> {
// Other code for class...
public bool Changed { get; private set; }
public void Save() {
Save(this); // I want the static method to handle saving the data
}
public static void Save(OrderInfo item) {
for (int i = 0; i < item.Count; i++) {
if (item[i].Changed) {
item[i].Save();
}
}
if (item.Changed) {
item.Save(); // this would be bad!
// Instead, all of the other developers should have to call the
// Database Save method.
// Is there a way to ensure this happens or do I have to rely on
// everyone remembering this?
}
}
}
编辑:使用标记的答案,我可以按如下方式编写我的课程(为什么无关紧要 - 这只会阻止递归):
public class OrderInfo : ICollection<UnitModule> {
// Other code for class...
bool saving; // <= new variable
public bool Changed { get; private set; }
public void Save() {
if (!saving) {
Save(this);
} else {
throw new Exception("This item is already being saved.");
}
}
public static void Save(OrderInfo item) {
item.saving = true;
try {
for (int i = 0; i < item.Count; i++) {
if (item[i].Changed) {
item[i].Save();
}
}
if (item.Changed) {
// item.Save(); <= NOTE: this would throw an exception
DataAccess.Save(item);
item.Changed = false;
}
} finally {
item.saving = false;
}
}
}
答案 0 :(得分:4)
通常情况下,超出堆栈限制时的崩溃会导致出现错误的警告。只要代码在投入生产之前得到了粗略的测试,就会有人抓住这个错误。
答案 1 :(得分:2)
这可能有效:
public static void Save(OrderInfo item) {
for (int i = 0; i < item.Count; i++) {
if (item[i].Changed) {
item[i].Save();
}
}
if (item.Changed) {
item.Changed = false; // prevents recursion!
item.Save();
if error saving then item.Changed = true; // reset if there's an error
}
}
答案 2 :(得分:2)
我不认为你的问题是不必要的递归。我认为你的问题是你已经实现了一个静态方法,它将类的一个实例作为唯一的参数。
为什么你甚至首先创建了一个静态方法?带有签名public void Foo.Bar(Foo f)
的任何方法的用例是什么?为什么要使用Foo.Bar(f)
代替f.Bar()
?我不知道这个问题可能有很好的答案。但这就是我先想到的。
答案 3 :(得分:1)
我会按优先顺序使用以下方法之一:
答案 4 :(得分:1)
这看起来像代码气味(如果某些东西可以“看起来”像“气味”)。我会考虑重构这个课程。为什么OrderInfo
有一个公共静态方法,看起来可以用来保存其他OrderInfo
个实例?
答案 5 :(得分:0)
你可以这样做:
private bool saving;
public void Save()
{
if(this.saving)
{
throw new InvalidOperationException("accidental recursion");
}
try
{
this.saving = true;
OrderInfo.Save(this); // I want the static method to handle saving the data
}
finally
{
this.saving = false;
}
}
但正如其他人所说,你应该可能重构你的代码,以减少错误。