I'm trying to better understand the use of properties, in particular within Unity game engine.
What I have to do is very simple: there is a class called "Enemy" that, every time it is instanciated (i.e. spawned), must access to the class GameSession and increase the value of a counter field, "numSpawnedEnemies", that however I want to be accessible through the property "NumSpawnedEnemies".
Note: GameSession is a singleton (i.e only 1 instance exists), but I omitted the related code for simplicity.
public class GameSession : MonoBehaviour
{
int numSpawnedEnemies = 0;
public int NumSpawnedEnemies
{
get
{
return numSpawnedEnemies;
}
set
{
Debug.Log("Value: " + value); // Just for debugging purpose
numSpawnedEnemies += value;
}
}
}
In the Enemy class I then do this, in the Start() method (i.e. the method automatically prompted by Unity for each instance of the Enemy class):
gameSession = FindObjectOfType<GameSession>();
// Unity function searching for the instance of GameSession
gameSession.NumSpawnedEnemies += 1;
The result, however, is not what I expected: in fact the counter "numSpawnedEnemies" gets increased every time x2 (i.e. 1, 2, 4, 8, 16, 32, 64...), rather than +1. That because, as the debug.console function shows, the value of "value" is, actually, 1, 2, 4, etc.
Setting the value to 0 (after assigning its value to numSpawnedEnemies) in the set {} doesn't change anything, but even if it would, that wouldn't explain to me this behaviour (in fact I expect that it get reset every time I access the property).
If I simply put numSpawnedEnemies as public and increment this field from the Enemy class, it works fine.
The questions then are:
How comes that "value" keeps track of a previous value? (shouldn't it be "reset" every time I access the property from some point?)
If answer to question 1 is that it is a normal behaviour, why does it get increased by x2 each time?
Thanks in advance!
You have += on both the property and the Enemy using it.
In the property replace
numSpawnedEnemies += value;
With
numSpawnedEnemies = value;
Short solution like
#Pino De Francesco said
change statement in property from
numSpawnedEnemies += value;
to
numSpawnedEnemies = value;
Explaination
You can treat the property like 'Get' and 'Set' method depend on you implenment.
So your NumSpawnedEnemies be like
void NumSpawnedEnemies(int value){
numSpawnedEnemies += value;
}
int NumSpawnedEnemies(){ return numSpawnedEnemies;}
then if you call NumSpawnedEnemies += 1
it equal you pass numberSpanwedEnemies + 1 as value
to NumSpawnedEnemies(int value)
then final equation of your statement is
numberSpawnedEnemies = numberSpawnedEnemies + value
numberSpawnedEnemies = numberSpawnedEnemies + (numberSpawnedEnemies + 1)
that why your result is double each time you called
Related
I got simple problem, but couldn't find solution:
Is it possible to check if given variable has been assigned?
int i;
// stuff happens
if (someTest(i));
i = 0;
Console.Write("now i is assigned for sure")
For value types, the variable is always assigned. There is a value there of some kind. Even so, if you try to read the variable before it is assigned the compiler will tell you and show an error: your code will not compile.
In case of you need to know given field set or not, you can have Property to control that field. in the setter you can control it, for example in below example isSet Boolean flag is updated when the value set. if you need to reset the flag based on another value you can add another condition in the setter.
private int i;
private bool isSet;
public int IProp
{
get { return i;}
set { isSet =true; i=value; }
}
// test
Console.WriteLine("Is Set:" + isSet);
IProp = 0;
Console.WriteLine("Is Set:" + isSet);
//results
//Is Set:False
//Is Set:True
Goal: In my property setter, I need to sometimes multiply the added/subtracted/incremented value to another variable.
For example, if I do the following code:
MyProperty+=1;
MyProperty++;
MyProperty-=1;
In my setter, I need that 1 to be available so I can multiply it to my value:
int myField;
public int MyProperty
{
get
{
return myField;
}
set
{
int variable = variableThatContainsTheOne * otherVariable;
myField= variable;
}
}
I currently am implementing a separate function setter but that is sloppy. And cant use the built-in "value" because that will be simply the updated "myField".
My questions are:
(A) Is there not a way to get that 1 by some built in value like "value"?
(B) Is there a creative way that you know of where I can encapsulate this into the property setter?
(C) Any way to know whether someone tried to increase, decrease, or set the value? (Encapsulated within the setter or property scope)
Suppose I call Print very often in my code.
Do I have to declare CurrentPosition as global or local variable?
I want to know which version is faster.
Option A:
int CurrentPosition = 0;
void Print(string key, int conc, int col, byte _color) {
if (col <= cMax ? col >= cMin : false) {
if (CurrentRows.TryGetValue(key + "#" + conc.ToString(), out CurrentPosition)) { //Row is in the vieport
grid.GetCell(CurrentPosition, col).Presenter.Background = new SolidColorBrush(Color.FromRgb(255, 255, 0));
}
}
}
Option B:
void Print(string key, int conc, int col, byte _color) {
int CurrentPosition = 0;
if (col <= cMax ? col >= cMin : false) {
if (CurrentRows.TryGetValue(key + "#" + conc.ToString(), out CurrentPosition)) { //Row is in the vieport
grid.GetCell(CurrentPosition, col).Presenter.Background = new SolidColorBrush(Color.FromRgb(255, 255, 0));
}
}
}
I propose to have a look under the hood to know how the C# compiler deals with these two options.
Let's say I have this simplistic class:
class Test
{
private int _currentPosition;
public int OptionA()
{
ImplOutParameter(out _currentPosition);
return _currentPosition;
}
public int OptionB()
{
int currentPosition;
ImplOutParameter(out currentPosition);
return currentPosition;
}
public void ImplOutParameter(out int position)
{
position = 1;
}
}
The two first methods are very similar to yours. The third one is here to test the out parameter implementation.
Let's compile this class in Release configuration. Using your favorite IL viewer, the method OptionA looks like:
It pushes the reference of the object on the stack twice to get the variable member reference and to call the ImplOutParameter method. Then it returns the value of the variable member.
The method OptionB looks like:
It pushes the reference of the object on the stack, pushes the address of the variable on the stack and call the ImplOutParameter method.Then it returns the value. It doesn't need to take time in order to allocate the variable.
Based on this analysis, I tend to say the OptionB implementation is a bit faster than the first one, but hey, this is very small. :)
If you're maintaining the state of CurrentPosition between calls and you're not passing the value into the method, then it needs to be outside. Otherwise, it starts fresh every time.
The best policy would be a third option of passing CurrentPosition into the method as a parameter, however, and maintain the state independent of the routine's code.
In terms of speed, allocation does take a small amount of time, but it's generally negligible. The "stack frame" will be lengthened regardless, and assigning a default value takes about as long as an assignment.
So, the most you'll save is a couple of cycles per call (i.e., nanonseconds), but yes, declaring it outside is going to be a hair faster.
If you want to know which is faster, test it. That's the only way to really be sure.
Always test performance if you're making a decision on what method to choose based on it. If it isn't worth testing, then you don't need the extra cycles.
That being said, the two methods are [i]functionally[/i] different, so your decision shouldn't be based on their speed. Option B sets CurrentPosition each time Print is called, whereas Option A sets CurrentPosition to 0 once and its value when Print is called is [i]not guaranteed to be 0[/i] so you should choose whichever option provides the correct function.
I can tell you that the speed different will likely be negligible, practically non-existent between the two.
Say I have my class, and I have the non-static variable
int x = 5;
After the code runs x is changed to something else, how can I get the value x started with using reflection?
Short answer: you can't.
If you implement some kind of custom transactional system, than it is possible. Out of the box: no luck.
And yes, the custom transactional system can be very simple: add another field or property that you use to 'remember' the initial value.
if i understand you correctly you want the initial value of the x.
for that you need another member or parameter to keep the first initializing of x. for example in your class:
int FirstX = -1;// or any other value you know ain't gonna come
bool firstInitial = true;
public int X
{
set
{
if(firstInitial)
{
FirstX = value;
firstInitial = false;
}
x = value
}
}
Now if you mean default value that is set at class level, you already know as it is constant other way would be creating an instance of the class for which you need default value.
ClassName className= new ClassName();
className.MyProp//This will always give default value.
new ClassName().MyProp //would also do.
If you want list of transactional values you need to implement it, reflection is not meant for that.
Hi in my opinion property of my object shouold be 2, but after this code, is still 1, why?
internal class Program
{
private static void Main(string[] args)
{
MyClass value = new MyClass() { Property = 1 };
value.Property = value.Property++;
Console.WriteLine(value.Property);
Console.ReadKey();
}
}
internal class MyClass
{
public int Property;
}
in my opinion this should value.Property = value.Property++; first put to value what is in value and the increment property of this object, why id doesn't work?
What this does is:
Evaluate value.Property on the right hand side (result is 1) and remember the result
Increment value.Property (now it's equal to 2)
Assign the remembered result to value.Property (it's now again equal to 1!)
If you change Property to a property with an explicit getter and setter and put some debugging code inside the setter, you will see that it does indeed change values 1 -> 2 -> 1.
If you changed value.Property++ to ++value.Property, the first two steps would be reversed, so we 'd have:
Increment value.Property (now it's equal to 2)
Evaluate value.Property on the right hand side (it's still 2)
Assign the result of step 2 to value.Property (it's still 2)
Of course, this is unnecessarily complicated and one could even say, wrong. If you want to increment Property, all you have to do is this:
++value.Property;
Because valueProperty++ is the same as the following:
int Increment(ref int value)
{
var temp = value;
value = value + 1;
return temp;
}
value.Property = value.Property++;
Here value.Property++ means it assing 1 before incrementing.
Because the = operator is lower down the order of operator precedence than increment.
http://msdn.microsoft.com/en-us/library/6a71f45d.aspx <- shows al the operators and their order of precedence.
The increment gets evaluated first completely. then the returned value from the increment is put through the = operator.