StackOverflowException in setter with property support

UPDATE: I fixed the problem I encountered, but I don't know why the error created a stack trace. The stack trace leads me in a completely wrong direction. If anyone can explain what is happening here, I would appreciate it (and mark your answer as accepted). Please note that my original message has been deleted.

I had the following class. Non-parts were deleted:

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; } } } 

I also had this class that took an instance of the class above and created an XML string using the values ​​from the instance:

 class SecondClass { private ClassName classnameInstance; public SecondClass(ClassName instance) { classnameInstance = instance; } public string PrepareRequest(XMLWriter writer) { writer.WriteElementString("accounttypedescription", classnameInstance.AccountTypeDescription); } } 

Here is the code for the client that generated the stack trace:

 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); } 

Finally, here is the stack trace:

 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 

This stack trace makes me think that I did not properly implement the receiver / setter for STPP.SettleDueDate. I checked them, and the backup variable, etc. It was correct (the usual reasons for loops in getters / setters, I understand). Further debugging showed me that the stack trace was actually generated when this PrepareRequest() line was PrepareRequest() :

 writer.WriteElementString("accounttypedescription", STPPData.AccountTypeDescription); 

I found that I used getter incorrectly for STPPData.AccountTypeDescription because I created the backing property that I used in setter, but I did NOT use the backing property in getter:

 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) } 

My question is:

Why does the stack trace of a StackOverflowException object point me to SettleDueDate.set () when the error was actually inside AccountTypeDescription.get ()?

Note. I am new to C # and am coming from the LAMP background. I simplified the code a bit, but I don’t think I deleted anything important.

+6
source share
2 answers

Below are some simple debugging steps that should narrow down the problem.

  • Open the class using the SettleDueDate property
  • Right Click Property Name for SettleDueDate
  • Click on the menu item "Find all links"
  • For each place where SettleDueDate is set, that is, "SettleDueDate =" Something or the other, "add a breakpoint
  • Launch the application and continue working when the breakpoints are deleted until one of them hits several times in a row.
  • When you find that the offending point and code are at a checkpoint, instead of continuing to use the Exit and Step-by-Step commands to track the path of the stack backup to find out where it is assigned recursively
+1
source

This code is very fragmented, and I'm not sure I fully understand all the connections. I assume that ClassName == STPPData and Secondclass == STPPXml? However, I tried to reproduce this error with VS2010 and .NET 4. I did not succeed - the stack trace showed infinite recursion only in AccountTypeDescription.set (). Something is missing there.

First of all, these lines in the stack trace are very interesting:

 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) 

They seem to definitively show the internals of SettleDueDate.set (), and not just endless calls to it. Dictionary and hash search are present. You definitely have a mistake somewhere there. However, I have a suspicion that your source code does not contain an error. Regarding @Bryan's answer, did you set breakpoints in the SettleDueDate setter as opposed to the places in the code where you name it? If you use visual studio, you can also disable exceptions using this function .

I saw that you do things using web services, and this immediately makes you think about proxy classes. They may look very awful, like the code you write, but this is not the code you write. They may become obsolete. How confident are you that this exception was thrown by code that you wrote and compiled?

Secondly, web services also make me think of serialization, a process that will often call getters and seters properties without your knowledge. I had problems in the past when WCF tried to serialize IEnumerables and fail, even though my code was ok.

As an aside, on my system this line did not compile:

 if (!_accountTypes.Contains(value)) 

This made me wonder if you are using a Mono or other IDE than me. You are still a guy LAMP =)

I know this is not a real answer (yet), but I wonder what you are doing to this? Any other data you can provide?

+1
source

All Articles