简体   繁体   中英

C# - Property is causing StackOverflow

public class ModelInfo
{
    public int AssignedCount { get; set; }
    public int UnassignedCount { get; set; }
    public int TotalCount { get { return UnassignedCount + TotalCount; } }
}

* Edit: * I realized when I put this code in SO that the TotalCount property is adding the UnassignedCount + the TotalCount (I meant to add the other two counts together). Can someone please provide a throughough explanation on why the SO error occurs though? I mean, the low-level stuff.

Stackoverflowing!

You're calling TotalCount from within TotalCount , don't do that.

You can have another field for the value of the property instead.

Though, I suspect your code should read as:

public int TotalCount { get { return UnassignedCount + AssignedCount ; } }

EDIT: as for why the stackoverflow occurs, it is because when you're using Properties, the .NET compiler will actually generate 2 functions, set_PropertyName and get_PropertyName . So in essense, it causes a stackoverflow from the get_PropertyName method call that becomes infinitely deep.

The easiest way to see what's happening (IMO) is to translate these properties into methods:

// If we didn't have properties, this is what the two first lines would be. Ick!
private int assignedCount;
private int unassignedCount;

public int GetAssignedCount()
{
    return assignedCount;
}

public void SetAssignedCount(int value)
{
    assignedCount = value;
}

public int GetUnassignedCount()
{
    return unassignedCount;
}

public void SetUnassignedCount(int value)
{
    unssignedCount = value;
}

// And here's the read-only TotalCount property translation
public int GetTotalCount()
{
    return GetUnassignedCount() + GetTotalCount();
}

Now the recursion within GetTotalCount() should be really clear. The method unconditionally calls itself, so blows up the stack eventually.

The mixture of auto-implemented properties and the fact that property accesses look like field accesses sometimes gets in the way of remembering that they're really just methods in disguise. Hopefully the translation above makes it all more obvious.

Can someone please provide a throughough explanation on why the SO error occurs though?

Sure: in order to calculate TotalCount , the compiler generates code like this:

  • Get UnassignedCount
  • Get TotalCount
  • Add UnassignedCount to TotalCount
  • Return the result

When calling the property getter of TotalCount (remember, a getter is a regular no-argument function that uses a special syntax), the runtime places the return address on the stack. The second step finds us back at the beginning, with one extra return address on the stack; the third step does it again, then the forth, the fifth, and so on. Each invocation deposits another return address on the stack. This continues all the way to the limit of the stack, at which point an exception is thrown.

You should be able to write this: You should note that TotalCount can never be set to so it would have no value. Did you perhaps mean to do this:

public class ModelInfo
{
    public int AssignedCount { get; set; }
    public int UnassignedCount { get; set; }
    public int TotalCount { get { return UnassignedCount + AssignedCount; } }
}

There is a mechanism called the "stack," used to track nested calls. When you call a method or function, the current "stack frame" (the address that control will transfer to when the method you called returns, as well as any parameters and method locals in your method) are pushed onto the stack. When control returns to your method, this stack frame is popped off and the CPU registers are restored to their prior state so that your method can continue executing.

The stack is a fixed allocation of memory, and therefore you can only call so many levels deep before you run out of places to store the information that is necessary to restore the state of the CPU registers when your function is returned to. At this point, a stack overflow error happens because, well, you overflowed the stack. You made so many nested calls that you ran out of memory to record them in.

That's why the exception happens. You recurse infinitely: your property getter calls itself over and over and over until there is no more room on the stack.

Because you are referring to TotalCount within the TotalCount getter. An infinite loop occurs until a stack overflow is reached.

You are looping round and round when trying to get the value for TotalCount

So roughly, the logic for getting TotalCount is:

  • Get value for UnassignedCount
  • Get value for Totalcount

repeat, rinse and wash.

Edit: as for why, have a look at Wiki

您处于无限递归中,一个自称的属性

Because the call stack would get (theoretically) infinitely deep. And you don't have an infinite stack to keep all the data you would need.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM