Variables retain their value in a loop? - c#

If I run this simple code in a console app:
For i As Integer = 1 To 10
Dim s As String = i.ToString()
Dim x As Decimal
If i = 1 Then
x = Decimal.Parse(s)
End If
Console.WriteLine(x.ToString())
Next
Console.ReadLine()
Unexpectedly, x retains its value of 1 and so 1 gets printed 10 times. I thought each iteration of the loop was its own code block, and that the state didn't carry over? Why does this happen? I would expect x to have the default value of System.Decimal.
Same thing happens in C#, except that the complier won't let you call ToString() on an uninitialized variable, but if you set a breakpoint in Visual Studio, you can see that x retains its value of 1.
for (int i = 1; i <= 10; i++)
{
string s = i.ToString();
Decimal x;
if(i == 1)
{
x = Decimal.Parse(s);
}
// Value of x remains 1
}
Console.ReadLine();

Regarding VB.NET take a look about scope here. In the "Block Scope" section there is a note which states the following:
Even if the scope of a variable is limited to a block, its lifetime is
still that of the entire procedure. If you enter the block more than
once during the procedure, each block variable retains its previous
value. To avoid unexpected results in such a case, it is wise to
initialize block variables at the beginning of the block.
So this behavior is by design and you should initialize the variable to whatever value your code needs.
I modified your code to show that the first time x is initialized to 0 but after that it retains the value of 1.
For i As Integer = 1 To 10
Dim s As String = i.ToString()
Dim x As Decimal
Console.WriteLine(x.ToString())
If i = 1 Then
x = Decimal.Parse(s)
End If
Console.WriteLine(x.ToString())
Next
Console.ReadLine()

thought each iteration of the loop was its own code block, and that the state didn't carry over
It does "carry over."
int i is scoped to the entire range of the loop, with values from 1 to 10.
The if statement only executes on the first iteration, and x is scoped as a local variable to the outer method (assuming the loop is entered), not only the loop body. That being said, after & outside the loop, x == 1 as well.
In fact, Decimal x; in the loop is redundant, and you have the same execution logic as
string s;
Decimal x;
for (int i = 1; i <= 10; i++)
{
s = i.ToString();
if(i == 1)
{
x = Decimal.Parse(s);
}
Console.WriteLine(x);
}
// x still defined here

To make some sense of what you want, it should be just like this:
For i As Integer = 1 To 10
If i = 1 Then
Console.WriteLine(Decimal.Parse(i.ToString()))
End If
Next
This will give you the same result you want but it is readable.

Related

How to make this code more functional or 'prettier'

I've been working on a project where I need on a button press that this line gets executed.
if (listView1.SelectedItems[0].SubItems[3].Text == "0") //Checks to see Value
{
listView1.SelectedItems[0].SubItems[3].Text = "1";// If Value is Greater, Increase and Change ListView
questionNumberLabel.Text = listView1.SelectedItems[0].SubItems[3].Text;// Increase and Change Label
}
Now I have this repeated about 10 times with each value increasing by one. But I know that this is ugly, and dysfunctional. As well as conflates the file size. I've tried a few things. Primarily this method.
if (listView1.SelectedItems[0].SubItems[3].Text == "0")
{
for (var i = 1; i < 100;)
{
if (!Int32.TryParse(listView1.SelectedItems[0].SubItems[3].Text, out i))
{
i = 0;
}
i++;
listView1.SelectedItems[0].SubItems[3].Text = i.ToString();
Console.WriteLine(i);
}
}
But instead of just adding one, it does the 100 instances and ends. The reason this is becoming a pain in the *** is because the
listView1.SelectedItems[0].SubItems[3].Text
is just that - it's a string, not an int. That's why I parsed it and tried to run it like that. But it still isn't having the out come I want.
I've also tried this
string listViewItemToChange = listView1.SelectedItems[0].SubItems[3].Text;
Then parsing the string, to make it prettier. It worked like it did before, but still hasn't given me the outcome I want. Which to reiterate is, I'm wanting the String taken from the list view to be changed into an int, used in the for loop, add 1, then restring it and output it on my listView.
Please help :(
You say you want the text from a listview subitem converted to an int which is then used in a loop
so - first your creating your loop variable, i, then in your loop you're assigning to it potentially 3 different values 2 of which are negated by the, i++. None of it makes sense and you shouldn't be manipulating your loop variable like that (unless understand what you're doing).
if you move statements around a little..
int itemsToCheck = 10; // "Now I have this repeated about 10 times "
for (var item = 0; item < itemsToCheck; item++)
{
int i;
if (!Int32.TryParse(listView1.SelectedItems[item].SubItems[3].Text, out i))
{
i = 0;
}
i++;
listView1.SelectedItems[item].SubItems[3].Text = i.ToString();
Console.WriteLine(i);
}
Something along those lines is what you're looking for. I haven't changed what your code does with i, just added a loop count itemsToCheck and used a different loop variable so your loop variable and parsed value are not one in the same which will likely be buggy.
Maybe this give you an idea. You can start using this syntax from C# 7.0
var s = listView1.SelectedItems[0].SubItems[3].Text;
var isNumeric = int.TryParse(s, out int n);
if(isNumeric is true && n > 0){
questionNumberLabel.Text = s;
}
to shortcut more
var s = listView1.SelectedItems[0].SubItems[3].Text;
if(int.TryParse(s, out int n) && n > 0){
questionNumberLabel.Text = s;
}

How does a for loop allow redeclaration of a variable?

This:
int j = 1;
int j = 2;
Console.WriteLine(j.ToString());
.. produces a compile error:
A local variable named 'j' is already defined in this scope
Yet this works fine:
for (int i = 0; i < 10; i++)
{
int j = i;
Console.WriteLine(j.ToString());
}
Why?
How does the loop simultaneous retain values from each iteration whilst being able to redeclare a variable with the same name in the same scope?
The variable j exists only per iteration, i.e. in each iteration a variable j is declared, assigned, used and then discarded and the next iteration begins and the process repeats and so forth. hence you don't get the same compilation error as the first example snippet.
When you write int j=1 and int j=2, you are trying to declare the variable twice (you can only declare it once).
You could, however, overwrite the value of j:
int j = 1; // now j has a value of 1
j = 2; // now j has a value of 2
This is what the for loop is doing - each iteration of the for loop, the value is updated. A new instance of j is not created during each iteration.
In the first example you are defining two variables with the same name, and they exist at the same time.
In the loop, every variable is created in the loop context. After each iteration the variable is destroyed, allowing you to create a new one with the same name(on the next iteration). In other words, on the loop they don't exist at the same time.

For Loop Iteration Solution

I have a basic grasp of For Loops in C#, but I'm having difficulty following this particular function. I have attempted to run the function in Visual Studio, but it results in an overflow exception.
"Describe what will happen when you call doSomething(5) given the following function:"
private void doSomething(int x = 10)
{
for(var y = 1; y <= x; y++)
{
Console.WriteLine(y);
if(y == 3)
doSomething(x);
}
}
Here's what I can see from analyzing the code. Starting from 1 the loop will check if y is <= 10. If y <= 10, it will write the value of y to the console. It will then check to see if y is equal to 3. If true, it will then call doSomething again, checking y against 10 again.
It is a recursive function, if you call doSomethig (5), when it enters the cycle will send to doSomethig the same value (in this case 5) forever.
If you create simulation how this code will assign values to variables, you will notice that y will always be assigned with 3, that means doSomething(x) will be called infinity times and calling something infinity times results to overflow exception.

How is the 'e--' expression used in this simple exponent example?

I understand every cog in this code with the exception of one part: the "e--;" within the While loop. Can anybody explain its importance to me?
public class Power
{
public static void Main()
{
int e;
int result;
for(int i=0; i < 10; i++)
{
result = 1;
e = i;
while(e > 0)
{
result *= 2;
e--;
}
Console.WriteLine(string.Format("2 to the {0} power is {1}", i, result));
}
}
}
You're looking at a postfix decrement operator.
It evaluates the value of e and then subtracts one from the value; since it's a standalone statement, it simply subtracts one from e's value.
The idea here is to simply multiply result by 2 i times. It does this by setting e to i, subtracting one each iteration of the loop, and looping while it's positive. This means that the while loop will always loop i times. You could just as easily (and arguably more clearly) write:
for(int e = 0; e < i; e++)
result *= 2;
while(e > 0)
This means that your loop will run as long as e is greater than zero. e-- is decrementing e's value on each iteration. If you didn't decrement it inside of your loop then you will get an infinite loop because your condition will become always true and your loop won't end.
The e-- just decrements the value of e. It is equivalent to e = e - 1;.
The reason you decrement the value is to eventually exit of the while loop; once you set e to the value of i, the loop will run indefinitely unless the value of e becomes less or equal to zero, which makes the while loop condition of e > 0 false.
In the larger picture, you are using e to stored the current value of i and then use it to execute i times the statement result *= 2;. In other words, you are using e to count how many times the variable result needs to be multiplied by 2 during the current iteration of the outer for loop.
This is similar to doing something like,
for (int i=0; i < 10; i++)
{
result = 1;
e = 0;
for (e = i; e > 0; e--)
{
result *= 2;
}
}
Since the while loop is really acting as a for loop.
e is your counter variable. It will repeat the while loop until the result has been multiplied the specified number of times (which is whatever i is when the loop started). As others have stated, e-- just decrements the value of e by one. You can read more here. This means that, in the code you provided, it will multiply result by 2 e times which mathematically will compute 2^i (i.e. 2^0 = 1, 2^1 = 2, 2^2 = 4, etc.).
e-- means it will decrease 1 in each loop, e++ will increase 1
check this article http://msdn.microsoft.com/en-us/library/36x43w8w.aspx

Order of operations when working with array index

Consider this loop:
int[] myArray = new int[10];
int myIndex = 0;
for (int i = 0; i < 10; i++)
{
myArray[myIndex++] = myIndex;
Console.WriteLine(myArray[i]);
}
This yields:
1
2
3
...
Because myIndex is post-incremented, and the right side is evaluated first, shouldn't the array index 0 contain 0?
Can someone explain this order-of-operations misunderstanding for me?
The right side isn't necessarily evaluated first. Similar to:
foo.Bar.Baz = a + b;
In the above code, foo.Bar is evaluated first, then a + b, then the set_Baz method is called to set the Baz property to whatever is evaluated on the right.
So in your code, if you break it into pieces, it looks like this:
var index = i;
// post-incremented in the original code means this comes after the line above,
// but not after the line below it.
i += 1;
myArray[index] = i;
first run:
myArray[myIndex++] = myIndex;
* *
| |
zero one
myIndex++ gets executed after myArray[myIndex++], but any subsequent calls with have the already incremented variable.
The myIndex++ is executing before the value is being set because the array index takes precident so it knows what array index to set the value to.
The...
myArray[myIndex++] = myIndex;
...is equivalend to...
int tmp = myIndex;
++myIndex;
myArray[tmp] = myIndex;
The myIndex++ is evaluated first, followed by the left side and finally the assign operator, according to precedence

Categories

Resources