Hi I have this program that I am writing that uses the struct below. I keep getting a stackoverflow error and the exception is stops the program at the fist bracket in public string sessionID set...(where the ">>>" is).
public struct SessionStruct
{
public string sessionID
{
get
{
return sessionID;
}
set
>>> {
sessionID = value;
}
}
public DateTime time
{
get
{
return time;
}
set
{
time = value;
}
}
public string type
{
get
{
return type;
}
set
{
type = value;
}
}
};
Here is the code that sets the struct:
if (type == "11" || type == "9")
{
s.sessionID = attributeArray[0].ToString();
s.time = DateTime.Now;
if (type == "9")
s.type = attributeArray[4].ToString();
}
else
{
s.sessionID = null;
s.time = DateTime.Now;
s.type = null;
}
Thanks for the help in advance...
you're doing an infinite recursion in that setter. Think about it.
Create a private member of a different name to get/set.
private string sessionID;
public string SessionID
{
get
{
return sessionID;
}
set
{
sessionID = value;
}
}
The sessionId Property setter calls it self, causing an eternal recursion.
Your property is calling itself over and over again. The property really needs a backing store to store the data in, which is typically a private variable:
private string _sessionID;
public string sessionID
{
get
{
return _sessionID;
}
set
{
_sessionID = value;
}
}
Or let the compiler do it for you:
public string sessionID
{
// compiler will create a backing store for you
get; set;
}
That is because the set property calls itself (the name is the same).
You probably want to use an autoproperty
public string sessionID
{
get; set;
}
The problem is that you're recursing on the sessionID property.
This:
public string sessionID
{
get
{
return sessionID;
}
set
{
sessionID = value;
}
}
Will be compiled to something like this:
public string sessionID_get() { return sessionID_get(); }
public void sessionID_set(string value) { sessionID_set(value); }
Obviously this won't work!
You should be using a backing field:
private string _sessionID;
public string sessionID
{
get
{
return _sessionID;
}
set
{
_sessionID = value;
}
}
Alternatively, you can get the compiler to automatically generate one for you:
public string sessionID
{
get; set;
}
Like everyone else has already said, you are doing an infinite recursion. Unlike everyone else, I'm going to explain you why an infinite recursion causes a stack overflow:
First, you need to understand that properties are just getter and setter methods (or functions, to speak more generically), only that they have a special syntax aimed to make the code that uses them more readable.
When some code attempts to set the property, behind the scenes the setter function is called, passing the value as an argument. Internally, your s.sessionID = attributeArray[0].ToString(); is essentially s.set_sessionID(attributeArray[0].ToString());. So your setter is being called. But the setter also attempts to set the property. In fact, the sessionID = value; is just a cleaner way to say set_sessionID(value);. So your setter is invoking the setter, again. This invocation will attempt to run the sessionID = value; statement, which invokes the setter, which attempts to run the statement, which invokes the setter, which... ok, I hope you get the idea.
A function that invokes itself is said to be recursive, and the technique itself is normally refered to as recursion. There are some good uses for recursion, but normally they use some form of conditional branching (so, eventually, the condition fails and the function stops calling itself and starts yielding results). On your case, however, you are going to the infinite and beyond: there is nothing on your code to stop the recursion (mostly because it wasn't intended to be recursive after all), so it will go on indefinitely. Well, not indefinitely, just until it crashes your program :P
Now, into the juicy part of this answer: what the heck is a StackOverflow? (aside from a nice Q/A website). Why aren't you getting something like an InfiniteRecursionException? Of course, the runtime doesn't know whether you messed up or you are just doing something unusual (actually, the runtime hopes you are doing something sane), so it trusts you and keeps doing what your code is telling it to do (in this case, call the property setter).
But for a function call to work, the runtime needs to push a "pointer" to the calling statemenet and the call arguments into the stack. The pointer is needed so the runtime can figure out where to go once the called function returns. And the arguments are needed so the function will know where to look for them (after all, it doesn't know from where will it be called). On each call, these things are pushed to the top of the stack, on top of everything that was already there.
Normally, the function would pop (retrieve and remove) the arguments, do some stuff, and return. At that point (the arguments aren't there anymore), the "return pointer" is on the top of the stack, so the runtime pops it and uses it to give control back to the caller.
It is because of this stacking mechanism (everything pushed goes on top of everything else, and stuff is only popped from the top of the stack) that chained calls can work (for example: function A calls function B which calls function C: when C returns, control will go back to B, not directly to A; but once B itself returns, control does go back to A).
What happens if you keep pouring water onto a glass? Normally it will fill up (unless it has a hole or something). But what if you keep pouring water onto it when it's already full? The water flows out of the glass, because it can't fit in. We could say that the water overflows from the glass.
Now, let's look again to your infinite recursion: each time you're setting the property, you are making (implicitly) a call to the setter, so a new "return pointer" and an argument (the value) are pushed onto the stack. Since the call makes a new call before it has a chance to return, it is pushing return pointers to the stack indefinitely before they get a chance to be popped. So the stack fills up, until it has no more memory available. At that point, the stack overflows. And, because there is absolutely no way for the program to continue without pushing stuff on the stack (which the runtime can't do because there is no more room for that stuff), the only option left is to complain about the issue. This complain from the runtime is what is commonly known as a StackOverflowException.
BTW, you can see (a simplified sample) of the call stack while debugging your program. Run it through Visual Studio's debugger (by default, you can do that by pressing F5) and wait for it to crash with the SO exception. Then look for the "Call Stack" window (I can't remember where it appears by default, have moved it countless times), and you will see how deep the runtime has been able to go on the recursion before running out of stack space. Your setter should show up there line after line, countless times.
And finally, a mention on the solutions: all you need to do is to avoid recursion. This means that you can't call your setter from inside your setter (by setting the same property from the setter). This also applies to getters (which are called upon getting).
The typical way to do this is to define a "backing" field for the property (a member variable where the value will actually be stored), and then from your setter and getter you set or return that field, respectively. Since the field needs to have a different name (a typical approach is to use an underscore (_) followed by the name of the property), the compiler will know that you are setting the field and not the property, so won't try to recursively call your property's setter.
Normally, setters are useful to perform "Sanity checks" (for example, you could check that the passed value is not null), but there are many situations when there is no need for checks on neither the setter nor the getter, and having to define the backing fields and the setters/getters themselves becomes boring, bloated, redundant, and error-prone. For this reason, C# supports "auto-implemented" properties: if you replace both accessors with get; set; (and the property is not abstract), the compiler will add a "nameless" backing field and the getting/setting code for you. Note that for this to work, you have to leave both accessors: if you want to define one of them, you'll also need to define the other.
If you have already understood the concepts, loot at the other answers to see many examples on how to apply them ;)
Hope this helps.
You have to use a backing field if you implement getter and setter yourself, otherwise it will keep calling itself on the setter, i.e like this:
private string _sessionId;
public string sessionID
{
get
{
return _sessionID;
}
set
{
_sessionID = value;
}
}
Since you don't actually need the implementations as you didn't put in any custom logic, use automatic properties:
public string sessionID {get;set;}
You're assigning sessionId to itself in your set accessor. (Recursively)
You need to split the field you're assinging to it's own backing field, or use an automatic property.
Like so:
private string _sessionId;
public string sessionID
{
get
{
return _sessionId;
}
set
{
_sessionId= value;
}
}
or automatic property:
public string sessionId { get;set ;}
Also note: You're other properties are going to have the same issue when you access the set accessor.
Related
I have a boolean variable, I want every change to its value to invoke a piece of code.
my current solution is the following:
bool _manualControl;
bool manualControl {
get {
return _manualControl;
}
set {
this._manualControl = value;
GlobalEventManager.ManualControlEvent?.Invoke(value);
}
}
this solution has two problems:
the value of "_manualControl" can be changed internally without invoking my piece of code, I want to prevent that.
I would prefer to avoid using two variables to get the desired behavior.
Is there any way to achieve what I want while avoiding these two specified issues?
You can set the property to be public and have a private backing field that can only be modified from within the class, which you have control of.
Or you could use an Aspect Oriented Programming framework like PostSharp, which would allow you to use an auto property and annotate it with the behaviour you desire. This would remove the need for you to have a backing field.
To me this sounds a bit like you want to solve an architectural problem, aka code smell. Why is it that you fear your field might be set outside your setter? Is it a particularly large class that a lot of people are chaning without really knowing what it is doing?
Why even have code in the setter? Like you could just redesign your code to have a method do what your setter code does and introduce that into your code flow / process.
And have a Unit Test validate your desired behavior.
If you want to:
ensure that the setter code always executes when a new value is assigned (inside and outside of the class)
avoid having two members in the class, that represent a single value
Then this can be approached by wrapping the value within a struct like one below:
struct Intercepted<T>
{
private readonly Action<T> _onChange;
private T _value;
public Intercepted(Action<T> onChange, T initialValue = default(T))
{
_onChange = onChange;
_value = initialValue;
}
public T Value
{
get
{
return _value;
}
set
{
_value = value;
_onChange?.Invoke(value);
}
}
}
In the class, ManualControl can now be represented with a single member, of type Intercepted<bool>:
public Intercepted<bool> ManualControl { get; } = new ManualControl(
onChange: newValue => {
GlobalEventManager.ManualControlEvent?.Invoke(newValue);
}
);
The value can be accessed like this:
// from within the class
if (ManualControl.Value) { ... }
// from outside
myObj.ManualControl.Value = true;
Now there is no way to change the value without triggering the setter code, both inside and outside the class.
I got the simplest property like
public bool Something { get; set; }
But in almost every one of them I need to call some method after set, so one line became
private bool _something;
public bool Something {
get{
return _something;
}
set{
_something = value;
CallMethod();
}
}
But it's broke all visual side of code.
So my question is if I can call setter method and stay with clear code?
As far I know, the simple answer is no. When you create your property with just a get and set, it's referred to as an auto-property. The compiler still creates the full code with the backing private variable.
What you have would be considered standard coding practice. It's a few extra lines of code, but easily readable.
Am I misunderstanding something about pass by reference?
SomeClass is the IObserver implementer:
bool value = false;
provider.Subscribe(new SomeClass(ref value));
while (!value)
{
provider.GetEvents() //triggers OnNext
}
In SomeClass:
public SomeClass(ref bool value)
{
this.value = value;
}
public void OnNext(object someUpdatedValue)
{
value = true;
}
Value never becomes true and the while loop never breaks. How come? Does assigning the value property of SomeClass to the reference of value not persist?
Edit: After seeing the first two responses my new question is this:
How can I achieve this kind of behavior without using static variables?
Pass by reference affects only the variable passed as the argument to the method. In your example, the value of false, which is what the variable value contained when you assigned it to this.value, is copied to the this.value field. Nothing more.
There's nothing magical in C# that will remember where that value came from and update the variable later, when the field to which its value was assigned is changed later.
Does assigning the value property of SomeClass to the reference of value not persist?
You aren't assigning "the reference of value". All that happens when you pass by-reference is that if the local variable itself is changed, then the variable that was passed is modified. When you use the value of the variable, you're only using the value, not the reference.
EDIT:
Without more context, it's impossible to say what the best way to approach this would be. But note that reference types achieve something similar to what you seem to be trying to do. For example:
class VolatileBoolWrapper
{
public bool Value { get { return _value; } }
private volatile bool _value;
public void SetValue(bool value)
{
_value = value;
}
}
VolatileBoolWrapper value = new VolatileBoolWrapper();
provider.Subscribe(new SomeClass(value));
while (!value.Value)
{
provider.GetEvents() //triggers OnNext
}
public SomeClass(VolatileBoolWrapper value)
{
this.value = value;
}
public void OnNext(object someUpdatedValue)
{
value.SetValue(true);
}
In that way, the VolatileBoolWrapper class acts as a go-between for the caller and callee.
<edit>
Note that I marked the field as volatile, and named the class Volatile... just to be safe. There's not enough context in the question for me to know what "triggers" actually means (i.e. does the same thread actually set the value, or is this something that involves interaction between threads).
If it happens that the call to OnNext() occurs within the same thread, strictly by virtue of the call to GetEvents(), then you can omit the use of volatile here (and ignore, or at least discount, my note about polling below).
</edit>
All that said, frankly: polling on a variable like this is pretty much always the wrong way to accomplish one's goals. There have always been much better approaches for things like this, but in modern C#, I would say that TaskCompletionSource is the best alternative. Like other mechanisms that came before it, it allows your waiting code to not continually use CPU time checking to see if the event has occurred; unlike them, it also provides an excellent mechanism for allowing that entire thread to continue executing, performing other work, only resuming at the await statement where you waited for the event when that event actually occurs.
The ref modifier affects the caller, not the callee. It allows you to reassign the caller's variable to "point to" a new value. For example:
bool myValue = true;
WithoutRef_YouCannotReassign(myValue);
Console.WriteLine(myValue); // myValue is still true
WithRef_YouCanReassign(ref myValue);
Console.WriteLine(myValue); // myValue is now false
void WithoutRef_YouCannotReassign(bool value) {
value = false;
}
void WithRef_YouCanReassign(bool value) {
value = false;
}
You're trying to pass out a reference to SomeClass.value. Normally, that'd work great by just swapping your assignment (remember, you're changing the caller's variable to point at something else)
public SomeClass(ref bool value)
{
value = this.value;
}
But, you've got another problem. Since a bool is immutable - even though your caller is pointing at the right value, you point your own value to something else later by overwriting it:
public void OnNext(object someUpdatedValue)
{
value = true; // value is now pointing somewhere else! the caller never got a reference to the somewhere else!
}
So, now, you actually need a wrapper to avoid having to overwrite SomeClass.value after you passed a reference out to it:
struct MyBoolWrapper
{
public bool Value { get; set; }
}
public SomeClass(ref MyBoolWrapper value)
{
value = this.value;
}
public void OnNext(object someUpdatedValue)
{
value.Value = true;
}
Now, this won't work because it's a struct (like bool is). structs are value types, and so the value of it gets copied back. When you change SomeClass.value, you're changing a different copy again! (This is one reason we tend to prefer immutable structs, like bool is).
So, let's change this to a class:
class MyBoolWrapper
{
public bool Value { get; set; }
}
This will work as expected since you end up passing back a reference to MyBoolWrapper (which doesn't change).
So, now we're working - but let's look at some cleanup. It seems a little silly for our caller to have to new a MyBoolWrapper just so that we can point it to something else. Let's change that:
MyBoolWrapper wrapper = null;
provider.Subscribe(new SomeClass(ref wrapper));
Well, now it seems silly that we set it to null. Since SomeClass is providing all the info, let's just make it an out (which, essentially, works the same as ref just without requiring it to be initialized):
MyBoolWrapper wrapper;;
provider.Subscribe(new SomeClass(out wrapper));
Of course, now it's not even clear why we can't just hold a reference to SomeClass directly, and get rid of this whole out/ref dance:
SomeClass someClass = new SomeClass();
provider.Subscribe(someClass);
while (!someClass.Value) {
provider.GetEvents();
}
class SomeClass {
public Value { get; private set; }
public void OnNext(object someUpdatedValue)
{
Value = true;
}
}
There - that's simpler. Since the caller has a reference to our instance that changes it's state (without changing it's identity), we don't have to worry about all of that method calling by-ref/by-val struct vs class mumbo-jumbo.
I have this property in my Class:
public string A
{
set
{
A = value;
}
}
It gives me an error whenever I try to assign a value to A. Actually, my IIS Express stops and gives no clue.
I have a feeling that this creates an endless assignment of value to A, it's like a recursion. My questions:
What is happening in my code?
Is property just an accessor (getter/setter) and not a container when you specify an implementation?
When using auto-implemented property, is the property both container and accessor?
You'll have a StackOverflow exception, since you're assigning the property itself in its setter, which results in an endless assignment.
You can not set property variable itself as a container..
you can write like this.
Scenario 1:
public string A
{
set;
}
Scenario 2:
private string _A=String.Empty;
public string A
{
set{_A=value;}
}
let me know if any question.
When you are using an auto implemented property, the compiler generates a container for the value and methods to work with that container (get and set).
When you implement the propriety yourself, like you did, the compiler only generates a set method, that then calls itself, resulting in an endless loop. The correct way to do it would be:
private string _a;
public string A
{
set
{
_a = value;
}
}
In this case, the compiler will generate a method to set the value of _a , and no recursion occurs.
Observe the following...
//pattern 1
public class Cheesesteak
{
public string bread {get; private set}
public string cheese {get; private set}
public Cheesesteak()
{
bread = "Amoroso";
cheese = "Cheez Whiz";
}
}
//pattern 2
public class Cheesesteak
{
public string bread
{
get {return bread;}
set
{
bread = "Amoroso";
}
}
public string cheese
{
get {return cheese;}
set
{
cheese = "Cheez Whiz";
}
}
public Cheesesteak() {}
}
This is a curiosity question. Is there any advantage or particular reason that you would set the variables in the definition of the "set" versus declaring them in the constructor? My initial guess is pattern 1 is shorter, but less efficient during compile.
Is there any advantage or particular reason that you would set the variables in the definition of the "set" versus declaring them in the constructor?
No, and in fact, this is probably not what you want at all. This will make it impossible to set "break" or "cheese", as any call, such as bread = "rye";, would set it to "Amoroso" (if it worked, but will cause a StackOverflowException). Also note that trying to retrieve the value in your code will cause a StackOverflowException, and the property getter returns the property and not a backing field value.
You were likely thinking of this:
public class Cheesesteak
{
private string bread = "Amoroso";
public string Bread
{
get {return bread;}
set
{
bread = value;
}
}
// ...
The only advantage here is you're setting the "default" value where the field is defined, which can help with maintainability or readability in some cases, and even potentially eliminate the need for a defined constructor, which might reduce the overall length of code.
My initial guess is pattern 1 is shorter, but less efficient during compile.
In general, setting the fields inline vs. setting them in a constructor does not make this less efficient. The compiler will cause the type's actual constructor to set the fields first then run the constructor code, so both versions end up (for practical purposes) the same in terms of the compiled IL. This isn't a matter of efficiency, but rather of code readability and maintainability.
Note that, if you wanted the property to always be a constant (ie: Bread should always return "Amoroso"), you can just make the property have a getter and no setter:
public string Bread { get { return "Amoroso"; } }
I suspect this is not the case, but I thought I'd mention it as an option just in case it's what you intended.
Well the second option will result in a StackOverflowException whenever a user tries to assign or access the properties, versus the first which will only allow private access to them.
You maybe meant something like:
private string bread = "Amaroso";
public string Bread
{
get { return bread; }
private set
{
bread = value;
}
}
Which will initialize the property with "Amaroso" but will not allow it to be set publicly.
No, they are completely different. The get and set blocks are actually methods that get executed when the property is read from or written to. Nether of them have anything to do with initialization.
var x = thing.Property; // Property's "get" accessor method is executed
thing.Property = x; // Property's "set" accessor method is executed
In your second example, both property accessors will infinitely recurse on themselves and you will get a StackOverflowException.