更新:我已经修复了我遇到的问题,但我不知道为什么这个bug会产生堆栈跟踪。堆栈跟踪导致我完全错误的方向。如果有人能够解释这里发生的事情,我会很感激(并且会将你的答案标记为已接受)。请注意,我的原始帖子已被删除。
我有以下课程。其中不相关的部分已被删除:
class ClassName {
private string[] _accountTypes = new string[2] {"ECOM", "MOTO"};
private Dictionary<string, string> _settleDueDateDictionary = new Dictionary<string, string>() {
{"0", "Process immediately."},
{"1", "Wait 1 day"},
{"2", "Wait 2 days"},
{"3", "Wait 3 days"},
{"4", "Wait 4 days"},
{"5", "Wait 5 days"},
{"6", "Wait 6 days"},
{"7", "Wait 7 days"},
};
private string _settleDueDate;
private string _accountTypeDescription;
public string SettleDueDate
{
get
{
DateTime today = DateTime.Today;
long settleDueDate = Convert.ToInt64(_settleDueDate);
return today.AddDays(settleDueDate).ToString("MM/dd/yyyy");
}
set
{
if (!_settleDueDateDictionary.ContainsKey(value)) {
// TODO - handle
}
_settleDueDate = value;
}
}
public string AccountTypeDescription
{
get {
//return AccountTypeDescription; // This would cause infinite recursion (not referring to backing property).
return _accountTypeDescription; // This fixed the StackOverflowException I was faxed with
}
set
{
if (!_accountTypes.Contains(value))
{
// TODO - handle
}
_accountTypeDescription = value;
}
}
}
我还有一个这个类,它接受了上面类的一个实例,并使用实例中的值创建了一个XML字符串:
class SecondClass
{
private ClassName classnameInstance;
public SecondClass(ClassName instance)
{
classnameInstance = instance;
}
public string PrepareRequest(XMLWriter writer)
{
writer.WriteElementString("accounttypedescription", classnameInstance.AccountTypeDescription);
}
}
以下是生成堆栈跟踪的客户端代码:
STPPData STPP = new STPPData();
STPP.SiteReference = _secureTradingWebServicesPaymentSettings.SiteReference;
STPP.Alias = _secureTradingWebServicesPaymentSettings.Alias;
STPP.SettleDueDate = Convert.ToString(_secureTradingWebServicesPaymentSettings.SettleDueDate);
STPP.SettleStatus = _secureTradingWebServicesPaymentSettings.SettleStatus;
STPPXml STPPXml = new STPPXml(STPP);
XmlWriterSettings settings = new XmlWriterSettings();
settings.Async = false;
var builder = new StringBuilder();
using (XmlWriter writer = XmlWriter.Create(builder, settings))
{
string xmlRequest = STPPXml.PrepareRequest(writer);
}
最后,这是堆栈跟踪:
mscorlib.dll!string.GetHashCode()
mscorlib.dll!System.Collections.Generic.GenericEqualityComparer<System.__Canon>.GetHashCode(SYstem.__Canon obj)
mscorlib.dll!System.Collections.Generic.Dictionary<string,string>.FindEntry(string key)
mscorlib.dll!System.Collections.Generic.Dictionary<System.__Canon,System.__Canon>.ContainsKey(System.__Canon key)
ClassName.SettleDueDate.set(string value)
ClassName.SettleDueDate.set(string value)
ClassName.SettleDueDate.set(string value)
// Infinite recursion of this call
这个堆栈跟踪让我相信我错误地为STPP.SettleDueDate实现了getter / setter。我检查了它们,支持变量等是正确的(我理解,getter / setter循环的常见原因)。进一步调试显示,当调用PrepareRequest()
这一行时,实际生成了堆栈跟踪:
writer.WriteElementString("accounttypedescription", STPPData.AccountTypeDescription);
我发现我错误地为STPPData.AccountTypeDescription实现了getter,因为我创建了一个我在setter中使用的支持属性,但我没有在getter中使用backing属性:
public string AccountTypeDescription
{
get {
//return AccountTypeDescription; // This would cause infinite recursion.
return _accountTypeDescription; // This fixed the StackOverflowException
}
// setter omitted for clarity (it is in the examples above)
}
我的问题是:
当错误实际存在于AccountTypeDescription.get()中时,为什么StackOverflowException的堆栈跟踪指向SettleDueDate.set()?
注意:我是C#的新手,我来自LAMP背景。我已经简化了一些代码,但我认为我没有删除任何重要的代码。
答案 0 :(得分:1)
下面是一些简单的调试步骤,可以缩小问题范围
答案 1 :(得分:1)
这段代码非常零碎,我不确定我是否完全了解所有连接。我假设ClassName == STPPData和SecondClass == STPPXml?尽管如此,我尝试使用VS2010和.NET 4重现此错误。我无法 - 堆栈跟踪仅在AccountTypeDescription.set()中显示无限递归。必须缺少一些东西。
首先,堆栈跟踪中的这些行非常有趣:
mscorlib.dll!string.GetHashCode()
mscorlib.dll!System.Collections.Generic.GenericEqualityComparer<System.__Canon>.GetHashCode(SYstem.__Canon obj)
mscorlib.dll!System.Collections.Generic.Dictionary<string,string>.FindEntry(string key)
mscorlib.dll!System.Collections.Generic.Dictionary<System.__Canon,System.__Canon>.ContainsKey(System.__Canon key)
它们似乎最终显示了SettleDueDate.set()的内部,而不仅仅是对它的无限调用。存在字典和散列查找。你肯定有一个错误某处。但是我有一个预感,你的源代码不包含bug。在参考@Bryan的回答时,您是否在 SettleDueDate setter中设置了断点而不是代码中你调用它的地方?如果您使用的是visual studio,则还可以使用this feature打破异常。
我看到你正在处理Web服务,并立即让我想到代理类。它们看起来很像你编写的代码,但它不是你编写的代码。他们可能会陈旧。您编写和编译的代码是如何引发此异常的?
其次,Web服务也让我想到了序列化,这个过程通常会在你不知情的情况下调用属性getter和setter。我以前遇到过一些问题,WCF尝试序列化IEnumerables并且尽管我的代码很好,但仍然失败了。
顺便说一句,在我的系统上,这一行没有编译:
if (!_accountTypes.Contains(value))
这让我想知道你是使用Mono还是使用与我不同的IDE。毕竟你是一个LAMP家伙=)
我知道这不是一个真正的答案(但是),但我想知道你对此有何看法?您可以分享的其他任何细节吗?