How this looping works in c# - c#

Recently, in a book i read this code. Can you define the means of this code and how this code works.
int i = 0;
for (; i != 10; )
{
Console.WriteLine(i);
i++;
}

It loops.
Since you already set i=0 above, they have omitted that section of the for loop. Also, since you are incrementing the variable at the end, they have omitted that as well.
They basically just turned a for loop into a while loop.
It would probably be more elegant as:
int i = 0;
while( i != 10 )
{
Console.WriteLine(i);
i++;
}

The for statement is defined in the C# spec as
for (for-initializer; for-condition; for-iterator) embedded-statement
All three of for-initializer, for-condition, and for-iterator are optional. The code works because those pieces aren't required.
For the curious: if for-condition is omitted, the loop behaves as if there was a for-condition that yielded true. So, it would act as infinite loop, requiring a jump statement to leave (break, goto, throw, or return).

If it's easier to see in normal form, it's almost the equivalent of this:
for (int i = 0; i != 10; i++)
{
Console.WriteLine(i);
}
With the exception that it leaves i available for user after the loop completes, it's not scoped to just the for loop.

You are using "for", like a "while"

It's the same as this loop:
for (int i = 0; i != 10; i++) {
Console.WriteLine(i);
}
Except, the variable i is declared outside the loop, so it's scope is bigger.
In a for loop the first parameter is the initialisation, the second is the condition and the third is the increment (which actually can be just about anything). The book shows how the initalisation and increment are moved to the place in the code where they are actually executed. The loop can also be shown as the equivalent while loop:
int i = 0;
while (i != 10) {
Console.WriteLine(i);
i++;
}
Here the variable i is also declared outside the loop, so the scope is bigger.

This code could be rewritten, (in the context of your code snippet - it is not equivalent as stated.) as:
for (int i = 0; i != 10; i++)
Console.WriteLine(i);
Basically, the initializing expression and the increment expression have been taken out of the for loop expression, which are purely optional.

It is same as:
for (int i = 0; i != 10; i++) {
Console.WriteLine(i);
}
Please don't write code like that.
It's just ugly and defeats the purpose of for-loops.

As int i was declared on top so it was not in the for loop.
this is quite like
for(int i = 0; i!=10; i++)
{
/// do your code
}

Related

Is using a math class method in a loop condition slow?

if i have a for loop for example and and i want to use something like Math.round() to round the number but i only need to round the number one time(i.e the number doesn't change throughout the loop) is it better to store it into a variable and then use the variable to in the condition or does it not matter?
for (int i = 0;i < Math.Round(x);i++)
{
//Some code
}
vs
for (int i = 0,roundedX = Math.Round(X); i<roundedX;i++)
{
//Some code
}
The compiler will evaluate the termination condition on every loop iteration.
The compiler and the JITter might hoist some expression or part of an expression outside the loop if it deems it is invariant, meaning it doesn't change. This, however, is usually only done with simpler expressions.
If the Math.Round(X) expression could've been done without an actual method call then perhaps but in this particular case the rounding will happen on each loop iteration.
As such, if you're at last line defense for performance problems, you might consider moving this out and into a variable:
int goal = (int)Math.Round(X);
for (int i = 0; i < goal; i++)
...
As this will call the Math.Round method only once, you only get the performance hit once.
Note that if X changes as part of the loop, then obviously you want to keep your original code.
I would suggest defining a variable
var roundedX = Math.Round(X);
for (int i = 0; i < roundedX; i++)
{
//Some code
}

Scope of a 'for' loop at declaration of a variable

I faced this strange behavior when I was coding. So I ask it here.
What is the scope of a for loop when declaring variables?
This code compiles fine
for (int i = 0; i < 10; i++) { }
for (int i = 0; i < 10; i++) { }
This means both int i are not in same scope.
But this code does not compile.
for (int i = 0; i < 10; i++) { }
int i; // Conflicts with both first loop and second one.
for (int i = 0; i < 10; i++) { }
This means the int i in middle of loops has the same scope of first loop and the second loop.
But how can int i in two for loops have different scope, but the same scope with middle int i? Because currently I see them at the same level.
I know the second code does not compile. Why does the first code compile then if there is problem in scopes. Is this an exception inside the compiler?
The C# compiler does not check whether a variable was declared before or after another variable. All that matters is the scope. The i variable declared between loops surely conflicts with the second loop, because if you use i inside the loop, there is no way to distinguish which i you'd like to use. As for the first loop, an error is still shown, because the block where i is declared encapsulates also the first loop.
For example, the following will not compile, even though j is not visible outside inner braces, so there should not be any ambiguity regarding i:
{
{
int i = 1;
int j = 1;
}
int i = 0; // compiler error: A local variable i cannot be declared in this scope (...)
// j is not visible here
}
Edit regarding the comment:
Why is the following fine?
{
for(int i = 1; i < 10; i++) {}
for(int i = 1; i < 10; i++) {}
}
When you declare a for loop variable, it is visible only inside the loop block. That means that the scopes of both variables are disjoint, since there is no line of code where one block "overlaps" the other one.
The scope of a for loop, for(INIT; COND; INCR) { BLOCK } is identical in scoping to
{
INIT;
while (COND) {
BLOCK;
INCR;
}
}
Thus a for loop can be best thought of as two nested scopes. (Note: the above conversion from for to while does not properly capture the behavior of continue. However, this question is not focused on that)
The issue you run into with the int i outside of the for loop is something called "shadowing." In C++, if you declared a scoped variable with the same name as something in an outer scope, you "shadowed it," silently covering it up until the scope ended. When they developed C#, they felt this was too counterintuitive, and too error prone. In C# it is a syntax error to shadow a variable from an outer scope. By introducing int i to the outer scope, it is now illegal for the for loops to introduce it themselves.
The variable declared in for loop has just scope inside for loop block, but when you declare a variable outside for loop, you cannot have same name variable inside the for loop, because it confuses compiler that which variable you mean in for loop body.
Like i will take your code as example:
int i =0;
for (int i = 0; i < 10; i++)
{
i = i+1; // now compiler is confused which i you mean here, so i complains on compile time that you have two with same name
}
So if you declare it between loops as you did, variable i has scope in both for loops so it is accessible in both for loops, so if you remove first loop it will still complain because of global scope of variable outside the loop:
for (int i = 0; i < 10; i++)
{
i = i+1; // now compiler is still confused which i you mean
}
int i =0;
I don't think it matters where you put int i;.
The compiler first scans the field, after which it starts scanning for expressions. It doesn't compile because the i is already recognized as a field.
There is nothing strange going on. In the second case you've defined an outer i and then try to redefine it in each loop.
Variables declared in a for statement are local to the loop, but you've already defined another variable with the same name in the outer scope.
I think you've already asked another scoping question assuming that the scope of a variable starts from the point of declaration ?
A variable's scope is the block in which it is defined, it isn't affected by its placement. While the compiler will refuse to use the variable before the declaration, it is still in scope
int i; You declare outside the loop is available for the current function. Either declare only outer int i, and remove int i from both loops, or just remove this outer variable.

Why for loop want take parameters of function in c#?

Why this code doesn't work?
private void Function(int starts , int ends)
{
int i = starts;
int z = ends;
for(i; i < z; i++)
{
[...]
}
}
It's say: Error 3 Only assignment, call, increment, decrement, and new object expressions can be used as a statement.
What to do to make code work?
What to do to make code work?
How about
for (; i < z; i++)
{
[...]
}
OR why creating an extra variable 'z' when you can do
for (int i = starts; i < ends; i++)
{
[...]
}
Why your code doesn't not work!!
Because syntax of for loop is
for (initializer; condition; increment or decrement)
{
}
You were not initializing i in initializer. You could initialize it (as my second snippet) or remove initializer if you are initializing it in some earlier statement(as my first snippet).
i in and of itself is not a statement, it's an expression. In the same way that you can-not simply write i; somewhere in your code. The initialization-part of a for-loop needs to be initialization; however, if (as is the case here) the loop is already initialized (i is already set), you can just omit it as Nikhil showed. Simply do for(;i<z;i++).
The first part of the for loop takes initialization statements. i is not a statement. If you don't want to initialize anything, you can leave that part empty, as in Nikhil's answer:
for(; i < z; i++)
{
[...]
}
Never use outside-defined variables as indexers in for loops.
private void Function(int starts , int ends)
{
// int i = starts; // don't do it. you're exposing yourself to headaches if/when you lose control of the value of i
int z = ends;
for(int i = starts; i < z; i++) //first statement of for loops initializes the indexer
{
[...]
}
}
I think this is the better answer is it not?
private void Function(int starts , int ends)
{
for(int i = starts; i < ends; i++)
{
[...]
}
}

c# syntax question - for loop and end of line

I am currently learning c# and reading a few books. I can do quite a few things, however only from modifying examples - it really frustrates that I do not actually understand how/why some of the more basic items work.
I have just done a console application that takes arguments and displays them all one by one.
The code is:
using System;
class test
{ static int Main(string[] argsin)
{
for (
int i = 0;
i < argsin.Length;
i++
)
Console.WriteLine("Argument: {0}", argsin[i]);
Console.ReadLine();
return -1;
}
}
Now, this works perfectly, but coming from a basic (no pun!) understand of Visual Basic, how/why does it know to print the correct argument and then go on to the next without quitting the application after the first Console.WriteLine... I feel I have missed the fundamentals of how this works!
Next, why is it that inside the for loop, each line ends with a semicolon apart from i++?
I keep forgetting to add it from time to time, and then when trying to work out why it wasn't compiling, I added one where I wasn't meant to!
Your code is formatted a bit strangely, if you reformat it as this I think it's easier to understand:
using System;
class test
{
static int Main(string[] argsin)
{
for (int i = 0; i < argsin.Length; i++)
{
Console.WriteLine("Argument: {0}", argsin[i]);
}
Console.ReadLine();
return -1;
}
}
So as you can see int i = 0; i < argsin.Length; i++ are not 3 different lines, they are all just arguments to the for loop.
And adding the { and } makes it easier to see what lines of code are inside the for loop.
I will try to explain the loop by comparing to VB syntax.
In C#: for (int i = 0; i < 5; i++)
In VB: For i = 0 To 4
The i = 0 part is the same in both, so I guess it's clear - this is used to initialize the loop iterator.
The i < 5 part in C# becomes 0 to 4 in VB.... you can think of this as though VB is doing a "shortcut", but the meaning in both is the same: that is the loop condition, i.e. what is the condition that the loop will keep running, in this case the loop will keep running as long as i is less then 5.
And finally, the i++ part which is required in C# to tell "what will happen to the iterator after each iteration?" is not needed in good old friendly VB that will simply increment it by 1 for you, always - by default.
Why having semicolon after each part of the loop? Because each part has its own meaning and usage so the compiler must know how to separate the parts when building the final code. Why not having semicolon after the i++ part? Same reason that you don't have comma after last argument passed to function e.g. Console.WriteLine("Argument: {0}", argsin[i], );
About the loop having no "block" only one line, it was explained in the other answers, rule of thumb is that C# allow single line blocks to appear without the brackets.
By convention c# and all c like languages when presented with a for loop (or and if statement etc) will run the line immediately after. Personally I don't like writing code like this, i feel it lacks readability.
To clarify we can add curly braces to denote scope
for (
int i = 0;
i < argsin.Length;
i++
)
{
Console.WriteLine("Argument: {0}", argsin[i]);
}
Console.ReadLine();
return -1;
now what the for loop executes is clearly defined (and if we wanted to do more in our loop we would add the extra instructions in between the curly braces).
edit:
The reason for the semi colons as you define your for loop is that each part of that definition is a separate statement.
int i = 0; //creates an integer i and sets its value to 0
i < argsin.Length; sets our comparison operation to define when the loop ends
i++ //what to do at the end in this case increment i by 1
Each needs to be treated independent of the others and as the semi colon denotes the end of a statement in c# (which is why each line ends in it) we use it to break up the statements so the compiler can read it.
While the 2 semicolons are mandatory the arguments are not we could if we wanted change it to be this.
int i = 0;
for (;;)
{
if(i>=argsin.Length){
break;
}
Console.WriteLine("Argument: {0}", argsin[i]);
i++;
}
This is functionally identical to the way you wrote it but I've moved all the logic out of the for statement to its equivalent position inside (or outside in the case of defining i) the loop
The reason why you application prints the right number of arguments is that the WriteLine statement is part of the loop. In C# if you've only got one line of code after a for statement then you don't need curly brackets. (This is the same for if too)
So
for (int i = 0; i < argsin.Length; i++)
Console.WriteLine("Argument: {0}", argsin[i]);
is the same as
for (int i = 0; i < argsin.Length; i++)
{
Console.WriteLine("Argument: {0}", argsin[i]);
}
As the for the semi-colon after the i++ thats just how it is. Normally the for statement is written on one line as I've done in my samples above.
Hope this helps.
I've brushed your formatting a little up, which gives you an easier understanding on how it works.
using System;
class test
{
static int Main(string[] argsin)
{
for (int i = 0; i < argsin.Length; i++ )
Console.WriteLine("Argument: {0}", argsin[i]);
Console.ReadLine();
return -1;
}
}
There's a special rule for C-like languages: You define it's scope using if(true) { ... } similar to If True Then ... End If, but if you only have one line, you can decide not to use brackets. Therefor the next line after the if or for[each] will be used for the scope.
The i++ does not end with a ; because it is within the declaration of the for.
Also, don't forget to have a look at the foreach loop.
If I rewrite your method with different formatting (but identical syntax), it may make things clearer:
static int Main(string[] argsin)
{
for (int i = 0; i < argsin.Length; i++)
{
Console.WriteLine("Argument: {0}", argsin[i]);
}
Console.ReadLine();
return -1;
}
Remember that c# doesn't use a line break for statement termination (unlike VB). The "third line" in your 'for' loop isn't actually a "line," it's just the third expression, and is terminated by the closing bracket.
The reason the loop continues rather than quitting is because (without squiggly brackets to indicate a statement block) the 'for' loop will only loop the single statement immediately following the loop - that is, the 'Console.WriteLine'. I'm guessing that you thought that the 'ReadLine' and 'return' statements would be part of the loop but, in C# syntax, that's not the case. (I added the bracess to my version to make the scope of the loop clearer).
I'll answer the part of your question...
for is a construct that has initializer, loop statement, and terminating condition.
So
for (X, Y, Z) { }
would be equivalent to
X;
while (Y)
{
// code
Z;
}
As for your question about not quiting the application - for () will bind to first NEXT statement, or statement BLOCK. In your case, you have only one line as a statement. If there would be more lines, you should write them encased in { and }.
Typical syntax for a for loop is:
for( int i = 0; i < argsin.Length; i++ )
{
//<CODE>
}
So you'd read it (in your mind) as: "With the temporary value 'i' starting at the value 0, while 'i' is less than 'argsin.Length', do '//' with i as the value, always ending with 'i++'"
A for loop just gets translated to:
{
int i = 0;
while( i < argsin.Lenth )
{
//<CODE>
i++;
}
}
(The extra surrounding braces are to say that 'i' goes out of scope and can no longer be used when the brace closes). Like any 'if' or 'while' statement the closing parenthesis provides the 'end-of-statement' "Character" (if you will) and so the semicolon is unnecessary. Earlier they are a must because you have to know where to end each statement.
[EDIT]
By the way: there's a little more to it than a straight translation. There are cases where you can include multiple initializations, and multiple 'at the end of each loop' instructions. Don't worry about those until you understand what's going on.
That is the basic of the for loop, in that loop, you declare that the starting value of integer i is zero and it should continue to loop until i is equal to the length of string[] argsin and increase the value of i on each iteration. Which means if the length of your argsin array is 5, the loop will
// first run
for(int i = 0;i<5;i++)
Console.WriteLine("Argument: {0}",argsin[0]);
// second run
for(int i = 1;i<5;i++)
Console.WriteLine("Argument: {0}",argsin[1]);
// third run
for(int i = 2;i<5;i++)
Console.WriteLine("Argument: {0}",argsin[2]);
// forth run
for(int i = 3;i<5;i++)
Console.WriteLine("Argument: {0}",argsin[3]);
// fifth run
for(int i = 4;i<5;i++)
Console.WriteLine("Argument: {0}",argsin[4]);
After 5 runs, i will be 5 and will not meet 5 < 5 and quit this loop and go on with the next statement.

Looping through a method without for/foreach/while

Is there a way of calling a method/lines of code multiple times not using a for/foreach/while loop?
For example, if I were to use to for loop:
int numberOfIterations = 6;
for(int i = 0; i < numberOfIterations; i++)
{
DoSomething();
SomeProperty = true;
}
The lines of code I'm calling don't use 'i' and in my opinion the whole loop declaration hides what I'm trying to do. This is the same for a foreach.
I was wondering if there's a looping statement I can use that looks something like:
do(6)
{
DoSomething();
SomeProperty = true;
}
It's really clear that I just want to execute that code 6 times and there's no noise involving index instantiating and adding 1 to some arbitrary variable.
As a learning exercise I have written a static class and method:
Do.Multiple(int iterations, Action action)
Which works but scores very highly on the pretentious scale and I'm sure my peers wouldn't approve.
I'm probably just being picky and a for loop is certainly the most recognisable, but as a learning point I was just wondering if there (cleaner) alternatives. Thanks.
(I've had a look at this thread, but it's not quite the same)
Using IEnumerable without foreach loop
Actually, the for loop does not hide what you're trying to do.
Anyone reading your code is already familiar with standard for loops and will understand instantly what you're doing.
You could score even more highly on the pretension scale by making it an extension method:
public static void Times(this int iterations, Action action)
{
for (int i = 0; i < iterations; i++)
{
action();
}
}
...
6.Times(() => {
DoSomething();
SomeProperty = true;
});
But I would definitely stick with a for loop. It's the idiomatic, well-recognised way of doing it.
Not a loop in sight
private MethodDelegate MultiMethod(MethodDelegate m, int count) {
MethodDelegate a;
if (count > 0) {
a = m;
a += MultiMethod(m, --count);
} else {
a = delegate { };
}
return a;
}
and you get a great syntax for invocation!
MultiMethod(action, 99)();
How about a do....until or if...then
Use a counter inside the loop and have it loop UNTIL the counter reaches 6.
Or an if-then statement with a counter. If your value is 6, break out of the loop.
I'm not a programming guru, but if you have an action that needs to be done a set number of times, there would be a need for a counter somewhere, whether it's a function of your loop or if it has to be created with a counter.

Categories