我有一个堆栈溢出错误,我很确定我没有任何类型的无限递归(至少我已经盯着错误几个小时了,我无法想象它是如何循环的无限)。
以下是代码:
public decimal? Amount
{
get
{
if (!string.IsNullOrEmpty(_savedWork.Amount))
return decimal.Parse(_savedWork.Amount);
else
return null;
}
set
{
if (value.HasValue)
{
_savedWork.Amount = value.Value.ToString();
Percent = null;
}
else
_savedWork.Amount = "";
OnPropertyChanged("Amount");
}
}
#注意我有一个以可以为空的十进制字符串的字符串,这就是我要转换它的原因。请不要让我说明为什么我这样做。
行savedWork.Amount = value.Value.ToString()
是我收到错误的地方。
基本上我认为我的堆栈太小(或者我认为我的代码太大了)。 我基本上运行这个代码两次,它在一种形式下工作,但是当我制作另一种形式并将其放在那里时,我不认为这两种形式之间的区别在于倾斜堆栈。 < / p>
有没有办法确定我做错了什么?我想知道代码的哪些部分占用太多或者持续时间太长等等。
我已经对堆栈/堆如何工作以及我对PerfMon.exe的了解做了一些研究,但据我所知它只适用于堆。是否有类似的工具,我可以用于我的程序正在运行的堆栈?
我发现了this post有关2个名为 windbg 和 cdb 的工具,但我找不到有关如何安装/使用它们的更多信息。这些工具是正确的方法吗?
或者,如果存在无限循环或某些事情会很棒。
这里是Amount属性所请求的代码(由EntityFramework自动生成)正如我在评论中所说,步骤甚至没有到达这里。我确实认为我的堆栈限制正在达到。
public global::System.String Amount
{
get
{
return _Amount;
}
set
{
OnAmountChanging(value);
ReportPropertyChanging("Amount");
_Amount = StructuralObject.SetValidValue(value, true);
ReportPropertyChanged("Amount");
OnAmountChanged();
}
}
好的, Meta-Knight 的答案告诉我,我确实有一个无限循环。我有一个事件处理程序订阅了DisplayTypeOfInvestment的PropertyChanged事件(Amount属性所属的类)。处理程序看起来像这样:
void DisplayTypeOfInvestmentList_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
_typeOfInvestmentFormSavedWork.TypeOfInvestment.Clear();
foreach (DisplayInvestmentFund d in _displayInvestmentFundList)
{
_typeOfInvestmentFormSavedWork.TypeOfInvestment.Add(d.SavedWork);
}
OnPropertyChanged("TypeOfInvestmentFormSavedWork");
}
TypeOfInvestmentFormSavedWork
是一个完全不同的类,其中包含它自己的SavedWork类版本,我们看到它使用的是Amount属性。此方法的目的是在Amount属性更改时将此TypeOfInvestmentFormSavedWork属性更新为_savedWork的新值。由于某种原因,这会触发DisplayTypeOfInvestment viewmodel的PropertyChanged。我没弄明白,但我把方法改成了这样:
void DisplayTypeOfInvestmentList_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == "Amount" || e.PropertyName == "Percent")
{
_savedWork.TypeOfInvestment.Clear();
foreach (DisplayInvestmentFund d in _displayInvestmentFundList)
{
_savedWork.TypeOfInvestment.Add(d.SavedWork);
}
OnPropertyChanged("CurrentWork");
}
}
当调用Add方法时,if语句会停止在DisplayInvestmentFund中更改奇怪的属性。
我意识到这个答案没有多大意义,但是对于我来说,详细解释这个问题会花费很长时间 。我也意识到这可能意味着我的代码很糟糕。我不知道该怎么做。谢谢你的帮助。
答案 0 :(得分:6)
我的猜测是,您在Amount
调用的一个事件处理程序中分配给OnPropertyChanged
。
另一种可能性是您在SavedWork.Amount
的设置器中有代码再次调用YourClass.Amount
。
但你为什么不调试呢?只需单步执行Visual Studio调试器中的代码即可。
堆栈跟踪也应该有用。通过无限递归,您通常会获得重复的方法序列。如果我的猜测是正确的,重复的部分将是:
MyClass.set_Amount
MyClass.OnPropertyChanged
OtherClass.myClass_amount_changed
答案 1 :(得分:2)
与_savedWork相同类型的Amount成员的类是什么?
因为可能有这个循环:
1)您为Amount
指定一个值2)在设置值之前,为_savedWork.Amount
指定一个值3)在设置_savedWork.Amount的值之前,再次触发该行
4)在设置_savedWork._savedWork.Amount的值之前......
5)在设置_savedWork._savedWork._savedWork.Amount的值之前...
这无穷无尽。
答案 2 :(得分:1)
必须以某种方式对Amount
setter进行递归调用。你可以通过“踩到”属性而不是踩到它来调试它。如果你设置VS使它不进入属性,你仍然可以在你的setter中放置一个断点来模拟“步入”。至于VS没有踩到.edmx文件,正如CodeInChaos所提到的那样,该类可能被标记为DebuggerStepThrough属性。
答案 3 :(得分:0)
_savedWork
是与您列出的Amount
属性相同类型的对象吗?因为将给你一个堆栈溢出错误!在这种情况下,您需要找到一种方式来讨论Amount
,而无需调用get
和set
。