|
The pre and post fix operations always affect the variable they are attached to: x++ or ++x will both increment the value of x by one, and they on there own will not affect the value of any other variables.
So when you use it in an expression:
int x = 10;
int y = ++x; the prefix op affects x only. y gets changed only because it is where the result of the expression on the RHS of the equals sign is stored when it is complete.
This is kinda difficult to explain without diagrams or being able to see your eyes glaze over...
Let's try this:
int x = 10;
int y = x++ + 5; This is evaluated as:
1) Set x equal to 10
2) Process the RHS of the line:
2.1) Get the value of x and save it for later
2.2) Incrmement x by one (so x is now 11)
2.3) Use the value you saved in 2.1 (10) and add 5 to it -> 15 save this as the result
3) Save the result of step 2 (which was 15) into y.
So you end up with x = 11, and y = 15
Prefix is the same process:
int x = 10;
int y = ++x + 5; This is evaluated as:
1) Set x equal to 10
2) Process the RHS of the line:
2.1) Incrmement x by one (so x is now 11)
2.2) Get the current value of x (11) and add 5 to it -> 16 save this as the result
3) Save the result of step 2 (which was 16) into y.
So pre- and post- fix ops affect the variable they are attached to, but when they affect them changes.
OK so far?
The universe is composed of electrons, neutrons, protons and......morons. (ThePhantomUpvoter)
|
|
|
|
|
my eyes glaze over long time ago, every time I open my book on C#… The clear mucus has to be removed with concrete trowel.
"The ++ and -- operators also support prefix notation, as described in Section 7.6.5. The result of x++ or x-- is the value of x before the operation, whereas the result of ++x or --x is the value of x after the operation. In either case, x itself has the same value after the operation."
<a href="http://msdn.microsoft.com/en-us/library/aa691363(v=vs.71).aspx">http://msdn.microsoft.com/en-us/library/aa691363(v=vs.71).aspx</a>[<a href="http://msdn.microsoft.com/en-us/library/aa691363(v=vs.71).aspx" target="_blank" title="New Window">^</a>
"In either case, x itself has the same value after the operation."
x has the same value, after were done evaluating the expression that it is in?
Did I understand that right?
In my exercise:
Start with the following assignments:
int x = 10;
int y = 100;
int z = y;
Then write a C# program to compute and display the values of the
variables y and z after executing these expressions:
y = y++ + x;
z = ++z + x;
So, now the variable y never really changes in the first expression. Using what MSDN described in their article, now the variable y returns to its original value of 100 even though it never really changed in the first place for the first expression. Right?
Now the second expression makes sense to me now on why it would be 111.
<a href="http://www.widmarkrob.com">My Coding Journey</a>
|
|
|
|
|
WidmarkRob wrote: Did I understand that right?
No, it's a bit badly explained: it isn't referring to the whole expression, just the little "x++" or "++x" bit - it doesn't matter if you do prefix or postfix, the value of x is the same after them both. That doesn't mean it is unchanged, just that it doesn't matter which you do, they both affect the variable in the same way.
y = ++x + 10;
y = x++ + 10;
What it's saying is that if x started at 100, in both cases it will be 101 afterward, despite y getting a different value each time.
WidmarkRob wrote: So, now the variable y never really changes in the first expression.
y does get changed by the postfix increment, it's just that the changed value is overwritten with the total from the whole expression.
The universe is composed of electrons, neutrons, protons and......morons. (ThePhantomUpvoter)
|
|
|
|
|
Aaaahhhh... maybe I get it now, maybe…
Give me a simple exercise… Maybe just barely, a little bit tiny bit harder than what I've been working with to see if I understand right.
I'll try to do it in my head really quick before I go and open Visual C# Express.
Your last line:
"y does get changed by the postfix increment, it's just that the changed value is overwritten with the total from the whole expression."
Kind of sort of little a lightbulb in my head.
D'oh
<a href="http://www.widmarkrob.com">My Coding Journey</a>
|
|
|
|
|
I like lightbulb moments!
Try this:
int x = 10;
int y = 100;
int z = ++x + (y++ * x);
Console.WriteLine("x = {0}, y = {1}, z= {2}", x, y, z); If you can work that out in your head, you are doing very, very well!
Normally, they don't get that complex - they are generally used for array indexes as such like:
byte[] data = File.ReadAllBytes(@"D:\Temp\MyFile.txt");
int i = 0;
do
{
if (data[i++] == 'x')
{
break;
}
} while (i < data.Length);
The universe is composed of electrons, neutrons, protons and......morons. (ThePhantomUpvoter)
|
|
|
|
|
x = 10
y = 100
z = 1112
lightbulbs still on?
<a href="http://www.widmarkrob.com">My Coding Journey</a>
|
|
|
|
|
I think you had a brief power cut...
The universe is composed of electrons, neutrons, protons and......morons. (ThePhantomUpvoter)
|
|
|
|
|
my electrons, neutrons and protons all turned into morons
<a href="http://www.widmarkrob.com">My Coding Journey</a>
|
|
|
|
|
Maybe one or two of them!
The universe is composed of electrons, neutrons, protons and......morons. (ThePhantomUpvoter)
|
|
|
|
|
Ah S4!T...
*Siiiiigh*
Let me look at it again…
This time I will type it out so you can see how I get my answers.
<a href="http://www.widmarkrob.com">My Coding Journey</a>
|
|
|
|
|
before I go look at it again… Did I get x and y right?
Is it z, that I got wrong?
<a href="http://www.widmarkrob.com">My Coding Journey</a>
|
|
|
|
|
z = 1012
???
<a href="http://www.widmarkrob.com">My Coding Journey</a>
|
|
|
|
|
Ok, let's look at it (though it's a PITA to work out, I admit) and substitute the values:
int x = 10;
int y = 100;
int z = ++x + (y++ * x);
1) ++x means "add one to x and use the new value", so x becomes 11 , and the calculation becomes
z = 11 + (y++ * x)
2) y++ means "Add one to y and use the old value", so y becomes 101 , and the calculation becomes
z = 11 + (100 * x)
3) We only have x left to worry about, so get the current value of it (which is 11 because we changed it in step 1) and the calculation becomes
z = 11 + (100 * 11)
Which is
z = 11 + 1100 Or
z = 1111
So the final result is:
x = 11, y = 101, z= 1111
This is a lot more complex than anything you should have to meet in "real life" (hence the discussion above about hitting people who do that kind of thing and why C++ will give you different results)
The universe is composed of electrons, neutrons, protons and......morons. (ThePhantomUpvoter)
|
|
|
|
|
okay, it is relieving I was only off by one
<a href="http://www.widmarkrob.com">My Coding Journey</a>
|
|
|
|
|
Welcome to the "I hit people who do that" club - your laminated membership card is in the post...
The universe is composed of electrons, neutrons, protons and......morons. (ThePhantomUpvoter)
|
|
|
|
|
This line is the important one:
int z = y-- + x;
it says to the computer, assign y + x into a variable called z. When you've done that knock one off the stored value of y.
so, in the line int z = y-- + x; z gets assigned with 100 + 10 (110) then y gets reduced to 99.
In the line z = --z + x;
The operation goes; knock one off z then assign the sum of z + x to z.
ie. take 1 off 110(z) to get 109; THEN assign 109+10 to z.
Basically if the ++ or -- is BEFORE the variable name (--y) then the operation is done BEFORE the rest of the line. But, if the ++ or -- is AFTER the variable name, the operation is done AFTER the rest of the line. Simples!
|
|
|
|
|
It's actually slightly more complicated, as I demonstrate here[^]
|
|
|
|
|
I know - BUT, why the hell would anyone write such a monstrosity.
Also, as it was clearly a beginner question, I was trying to simplify.
So you get 10/10 for correctness but 2/10 for being clear for the sake of the OP..
|
|
|
|
|
It would also matter in the cases of y = y++ + x; which OP is trying to understand..
|
|
|
|
|
wait a minute?
Who gets 10/10 for being correct?
OG or Me?
<a href="http://www.widmarkrob.com">My Coding Journey</a>
|
|
|
|
|
dynamic dynamicFail = (o1, e1) => { MessageBox.Show("store in 'dynamic"); };
var varFail = (o2, e2) => { MessageBox.Show("store in 'var"); }; However, you can assign a lambda to 'Action, or 'Func:
Action<dynamic,dynamic> myAction = (o3, e3) => { MessageBox.Show("Action works"); };
Func<dynamic, dynamic, string> myFunc = (o4, e4) => {return "Func works";}; In the MSDN docs, there is a comment on 'Func, that: Quote: The underlying type of any lambda expression is a Func. And, of course, in the MSDN docs for Lambda Expressions, you are told a lambda is an anonymous function "you can use to create delegates or expression tree types."
I am having trouble forming some kind of useful "mental model" about exactly what a lambda is, and how it can be used (in spite of having Skeet's 2nd. edition of "C# in Depth" at hand).
I know we can define an Event with a lambda: so, a lambda can become an EventHandler:
button1.Click += (obj, eva) => { MessageBox.Show("button1 clicked"); }; Where this "comes home to roost" for me is when I want to pass a lambda expression as a parameter to a method. You can certainly pass an Action<dynamic,dynamic> to a method, as a parameter:
private void MethodTakesAFunc(Func<dynamic, dynamic, string> theFuncParam){} While you can execute a passed in Func like this:
private void MethodTakesAFunc(Func<dynamic, dynamic, string> theFuncParam)
{
MessageBox.Show(theFuncParam(null, null));
} To me this way of getting execution by passing in null parameter stubs just seems absolutely weird: is there a simpler way ?
I see a similar problem with passing a lambda expression as a parameter to a method that then attempts to assign that lambda to an EventHandler.
Right now the only way I know to allow either an EventHandler, MouseEventHandler, or KeyPressHandler, to be passed in to a method, and then validly "wired up" to a Control's Event is something like this:
private void BindControlToClickEvent(Control theControl, dynamic theEventParam)
{
theControl.Click += theEventParam;
}
EventHandler myClickEvent = new EventHandler((obj, evn) => { MessageBox.Show("myClickEvent");});
BindControlToClickEvent(button2, myClickEvent); And that seems kind of "kinky."
I hope I have exposed enough of my confusion that diagnosis of my condition can proceed I'd really appreciate any guidance !
thanks, Bill
Humans are amphibians: half spirit, half animal; as spirits they belong to the eternal world; as animals they inhabit time. While their spirit can be directed to an eternal object, their bodies, passions, and imagination are in continual change, for to be in time, means to change. Their nearest approach to constancy is undulation: repeated return to a level from which they repeatedly fall back, a series of troughs and peaks.” C.S. Lewis
modified 28-Apr-13 1:18am.
|
|
|
|
|
It's just like the compiler told you... you can only "point" to a lambda via a delegate type. Dems da rules. Sorry.
BillWoodruff wrote: private void MethodTakesAFunc(Func<dynamic, dynamic, string> theFuncParam)
{
string evalFunc = theFuncParam.DynamicInvoke();
}
I don't get it... this works just fine:
private void MethodTakesAFunc(Func<dynamic, dynamic, string> theFuncParam)
{
string s = theFuncParam(someRandomVar1, someRandomVar2);
}
As for the uses of a lambda... well, some people "var them all up". What I mean by that is, I've seen a lot of C# code where people go hog wild with var...
var x = 0;
var y = new List<int>();
etc. Not what a var is intended for at ALL. I've seen people similarly write several page long functions in an inline lamda just cuz they are too lazy too create a function. Style wise, I think if your lambda code is < 5 lines or so, its fine to put it inline, but anything more then that it should be a separate function.
One trick you can do with lambdas is to change a methods signature. Typical UI event handlers are object sender, EventArgs e. Lets say you don't find any of those params useful, and you instead want to pass in a structure. That would require making that structure a class variable so the event handler can access it, but instead you can do:
button.Clicked += (x, y) => { MyEventHandler(someLocalObject); }
|
|
|
|
|
Thanks for your response, SledgeHammer01,
I've revised the section about which you commented, "I don't get it... this works just fine," in a way where I hope my sense of the weirdness of getting a passed in Func to evaluate is clearer.
I have no problem at all with the use of 'var as a way to save repetitious entry of complex object Types on "both sides" of an assignment statement: MS's documentation clearly tells you that is one of two primary uses 'var is for. The other use, of course, is to conveniently hold complex "unknown" Types returned by, for example, a Linq operation.
What I think is "bad practice," with using 'var, is to create a variable name that's not mnemonic, that doesn't "shout" at you, wherever you are in the code, what kind of object it contains, and/or how it's used, but you could say that about any variable name, imho.
Your example of "changing a method's signature" in a lambda used as an EventHandler is interesting, but I don't really see how you are in any way changing the signature of any method. In my view you are just inserting a call to another Method in the executable code body of the EventHandler. Perhaps if I saw your code that creates 'MyEventHandler, I'd "get" what you're demonstrating.
yours, Bill
Humans are amphibians: half spirit, half animal; as spirits they belong to the eternal world; as animals they inhabit time. While their spirit can be directed to an eternal object, their bodies, passions, and imagination are in continual change, for to be in time, means to change. Their nearest approach to constancy is undulation: repeated return to a level from which they repeatedly fall back, a series of troughs and peaks.” C.S. Lewis
|
|
|
|
|
I'm not sure what you are getting at with passing in nulls to execute the lamdba. If you have two dynamics as parameters to the function, that means you can pass anything into them, but you should pass something.
What I was demonstrating with changing the signature of a function is:
private void SomeMethod()
{
// random code here
// some more random code here
SomeComplexObject o = ...; // SomeComplexObject is built from the above random code
theButton.Click += MyEventHandler;
}
Ok, so without lamdas, how do you get "o" to MyEventHandler? You'd have to make it a class member, right? Seems lame to store a local object as a class member just for the sake of passing it to an event handler.
private void SomeMethod()
{
// random code here
// some more random code here
SomeComplexObject o = ...; // SomeComplexObject is built from the above random code
theButton.Click += (x, y) => { MyCoolerEventHandler(o); }
}
No, I didn't really "change the sig of the method" per say if you want to nitpick, but I passed o to my event handler in what I think is a much cleaner way then making it a class member.
One use of that is lets say you have a static object for whatever reason that has an event that takes an x & y. Without lamdas, you have no way to pass additional stuff into that function.
class MyClass
{
private static SomeClassWithEvents;
MyClass()
{
SomeClassWithEvents.theEvent += theHandler;
}
static void theHandler(x, y)
{
}
}
what if I want the handler to have access to SomeClassWithEvents... I'd either have to add a static "this" pointer:
static MyClass classPtr;
and init that.. or I could just do:
SomeClassWithEvents.theEvent += (x, y) => { theHandler(x, y, this); }
modified 28-Apr-13 2:13am.
|
|
|
|
|
You can't assign a lambda expression to a variable declared as var or dynamic because the compiler doesn't know whether you want an Action<> or an Expression<Action<>> .
Action<object> action = x => MessageBox.Show(x.ToString());
Expression<Action<object>> expression = x => MessageBox.Show(x.ToString());
var whatAmI = (object x) => MessageBox.Show(x.ToString());
You can help the compiler out with a few simple helper methods:
public static class Lambda
{
public static Action<T> Action<T>(Action<T> action)
{
return action;
}
}
var action = Lambda.Action((object x) => MessageBox.Show(x.ToString()));
dynamic myAction = Lambda.Action((dynamic x) => x.DoSomethingCool());
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|