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
}
Related
This question already has answers here:
Is there an elegant way to repeat an action?
(11 answers)
Closed 5 years ago.
A common pattern in coding is to use a iteration variable to do something certain number of times. In many cases, the iteration variable is only used as loop termination condition but adds several lines of code for the purpose.
Example,
int counter=100;
while ( counter > 0)
{
//Do something
counter--;
}
Does the .NET framework provide a way to define a coding block (Do something in example) and then execute it a given number of times, thereby removing the condition checking and decrementing statements above. This is to reduce the number of visible statements.
Edit: I am looking for way to reduce the number of codes, not make the underlying call efficient.
whats wrong with
for (int counter = 0; counter < limit; counter++)
{
//Do something
}
its an instantly recognizable idiom
There is no option in .NET Framework to do something N times without keeping track of number of times you already did something.
But you can write your own extension which will hide all this stuff. E.g.
public static void Times(this int count, Action action)
{
if (count < 0)
throw new ArgumentException(nameof(count));
for(int i = 0; i < count; i++)
action();
}
Usage:
100.Times(() => Console.WriteLine("hello"))
Note that if you'll extract the code which you want to repeat into method which matches Action signature, then the code above becomes cleaner:
100.Times(DoSomething);
You could use the Enumerable.Repeat to do the trick, not sure if it's really what you thought of elegance
Edit :
Little example how you can generate 100 different random values with this method. With a little adaptation it could suit your need
var ran = new Random();
var results = Enumerable.Repeat<Func<int>>(ran.Next, 100)
.Select(f => f())
.ToArray();
Edit:
I thought you could make it on your own, but some people need clarifications :
Enumerable.Repeat(100, () =>
{
// Do what you want
});
Source (for more details):
http://geekswithblogs.net/BlackRabbitCoder/archive/2012/05/03/c.net-little-wonders-the-enumerable.repeat-static-method.aspx
My question is, that when I loop through a list with for loop, and add elements to it during this, does it count the elements added while looping?
Simple code example:
for (int i = 0; i < listOfIds.Count(); i++) // Does loop counts the items added below?
{
foreach (var post in this.Collection)
{
if (post.ResponsePostID == listOfIds.ElementAt(i))
{
listOfIds.Add(post.PostId); // I add new item to list in here
}
}
}
I hope my explanation is good enough for you to understand what my question is.
Yes, it usually does. But changing a collection at the same time you're iterating over it can lead to weird behavior and hard-to-find bugs. It isn't recommended at all.
If you want this loop run only for preAdded item count then do this
int nLstCount = listOfIds.Count();
for (int i = 0; i < nLstCount ; i++)
{
foreach (var post in this.Collection)
{
if (post.ResponsePostID == listOfIds.ElementAt(i))
{
listOfIds.Add(post.PostId);
}
}
}
Yes it surely will.The inner foreach loop will execute and add the elements the outer collection and thus will increament the count of the elements.
listOfIds.Count=2 //iteration 1
listOfIds.Add(//element)
when it come to the for loop again
listOfIds.Count=3 //iteration 2
As a slightly abridged explanation of the for loop. You're essentially defining the following:
for (initializer; condition; iterator)
body
Your initializer will will establish your initial conditions, and will only happen once (effectively outside the loop).
Your condition will be evaluated every time to determine whether your loop should run again, or simply exit.
Your iterator defines an action that will occur after each iteration in your loop.
So in your case, your loop will reevaluate listOfIds.Count(); each time, to decide if it should execute; that may or may not be your desired behaviour.
As Dennis points out, you can let yourself get into a bit of a mess (youy loop may run infinitely) if you aren't careful.
A much more detailed/better written explanation can be found on msdn: http://msdn.microsoft.com/en-us/library/ch45axte.aspx
What is wrong with the following for loop syntax the crv variable is an array and I want an increment of 2:
for(int i<0; i<crv.Count;i+2)
{
//Code Here
}
My compiler only says Semicolon expected which is not a very useful feedback...
You need to start out initializing i to zero, not comparing it to zero. Additionally your last statement doesn't actually change i, it just returns a value of i+2 and does nothing with that value, you need to actually set i to that result.
for(int i = 0; i < crv.Count;i+=2)
{
//Code Here
}
The biggest error is that i+2 is not reassigned to i.
for(int i = 0; i<crv.Count;i = i+2)
{
//Code Here
}
You are throwing away the increment and i never changes value.
Then, you are not initializing i but checking whether it is less than 0.
Please note: first section is assignment You can't use comparison as int i<0;, instead it should be int i=0 or int i = -10 or anything similar as required.
Also in the increment section, either assign the updated value back to i
for(int i =0; i<crv.Count; i+=2)
{
//Code Here
}
or do the same in the body (just mentioning the option, which is useful in some specific scenarios)
for(int i =0; i<crv.Count;)
{
//Code Here
i+=2;
}
While most of these answers do tell you how to fix your code they don't tell you why it doesn't work which I think is important for you to understand.
a for loop consists of three parts, separated by semicolons.
for(part1;part2;part3)
part1 is executed only once - when the execution of the loop first begins. (this is normally where you assign an initial value to your counter)
part2 is then executed next, checking if its value is true or false.
If is true, then the body of the loop is executed
Then part3 is executed, (as you're attempting to do) this is normally where you increment
Then part2 is checked again, if its true, it goes through the process again, if its false it exists the loop
The first part of the for loop decides on i's initial value. in your example, you have "<", which isn't a solid value. Try i=0 instead. also, the last part reads as i, in addition to 2, instead of adding two each iteration. try i+=2 instead.
In .NET, using "foreach" to iterate an instance of IEnumerable will create a copy? So should I prefer to use "for" instead of "foreach"?
I wrote some code to testify this:
struct ValueTypeWithOneField
{
private Int64 field1;
}
struct ValueTypeWithFiveField
{
private Int64 field1;
private Int64 field2;
private Int64 field3;
private Int64 field4;
private Int64 field5;
}
public class Program
{
static void Main(string[] args)
{
Console.WriteLine("one field");
Test<ValueTypeWithOneField>();
Console.WriteLine("-----------");
Console.WriteLine("Five field");
Test<ValueTypeWithFiveField>();
Console.ReadLine();
}
static void Test<T>()
{
var test = new List<T>();
for (int i = 0; i < 5000000; i++)
{
test.Add(default(T));
}
Stopwatch sw = new Stopwatch();
for (int i = 0; i < 5; i++)
{
sw.Start();
foreach (var item in test)
{
}
sw.Stop();
Console.WriteLine("foreach " + sw.ElapsedMilliseconds);
sw.Restart();
for (int j = 0; j < test.Count; j++)
{
T temp = test[j];
}
sw.Stop();
Console.WriteLine("for " + sw.ElapsedMilliseconds);
sw.Reset();
}
}}
And this is the result that I got after I ran the code:
one field
foreach 68
for 72
foreach 68
for 72
foreach 67
for 72
foreach 64
for 73
foreach 68
for 72
-----------
Five field
foreach 272
for 193
foreach 273
for 191
foreach 272
for 190
foreach 271
for 190
foreach 275
for 188
As we can see in the result, "foreach" always takes more time than "for".
So should I prefer to use "for" instead of "foreach" when iterating through a generic collection of value type?
Note: thanks for the reminder, I edited the code and result. but still, foreach is running slower than for.
Your question is way, way too complex. Break it down.
Does using “foreach” to iterate a sequence of value types create a copy of the sequence?
No.
Does using "foreach" to iterate a sequence of value types create a copy of each value?
Yes.
Does using "for" to do an equivalent iteration of an indexed sequence of value types create a copy of each value?
Usually, yes. There are things you can do to avoid the copying if you know special things about the collection, like for instance that it is an array. But in the general case of indexed collections, indexing the sequence returns a copy of the value in the sequence, not a reference to a storage location containing the value.
Does doing anything to a value type make a copy of the value?
Just about. Value types are copied by value. That's why they're called value types. The only things that you do to value types that do not make a copy are calls to methods on the value type, and passing a value type variable using "out" or "ref". Value types are copied constantly; that's why value types are often slower than reference types.
Does using "foreach" or "for" to iterate a sequence of reference type copy the reference?
Yes. The value of an expression of reference type is a reference. That reference is copied whenever it is used.
So what's the difference between value types and reference types as far as their copying behaviour is concerned?
Value types are copied by value. Reference types copy the reference but not the thing being referred to. A 16-byte value type copies 16 bytes every time you use it. A 16 byte reference type copies the 4 (or 8) byte reference every time you use it.
Is the foreach loop slower than the for loop?
Often it is. The foreach loop is often doing more work, in that it is creating an enumerator and calling methods on the enumerator, instead of just incrementing an integer. Integer increments are extremely fast. Also don't forget that the enumerator in a foreach loop has to be disposed, and that can take time as well.
Should I use the for loop instead of the foreach loop because the for loop is sometimes a few microseconds faster?
No. That's dumb. You should make smart engineering decisions based on customer-focussed empirical data. The extra burden of a foreach loop is tiny. The customer will probably never notice. What you should do is:
Set performance goals based on customer input
Measure to see if you've met your goals
If you have not, find the slowest thing using a profiler
Fix it
Repeat until you've met your goals
Odds are extremely good that if you have a performance problem, changing a foreach loop to a for loop will make no difference whatsoever to your problem. Write the code the way it looks clear and understandable first.
Your test is not accurate; in the foreach version, you're actually spinning up the enumerator and retrieving each value from the list (even though you aren't using it). In the for version, you aren't doing anything with the list at all, other than looking at its Count property. You're essentially testing the performance of an enumerator traversing a collection compared to incrementing an integer variable an equivalent number of times.
To create parity, you'd need to declare a temporary variable and assign it in each iteration of the for loop.
That being said, the answer to your question is yes. A copy of the value will be created with every assignment or return statement.
Performance
This pseudocode breakdown should explain why foreach is somewhat slower than using for in this particular instance:
foreach:
try
{
var en = test.GetEnumerator(); //creates a ListEnumerator
T item;
while(en.MoveNext()) // MoveNext increments the current index and returns
// true if the new index is valid, or false if it's
// beyond the end of the list. If it returns true,
// it retrieves the value at that index and holds it
// in an instance variable
{
item = en.Current; // Current retrieves the value of the current instance
// variable
}
}
finally { }
for:
int index = -1;
T item;
while(++index < test.Count)
{
item = test[index];
}
As you can see, there's simply less code in the for implementation, and foreach has a layer of abstraction (the enumerator) on top of the for. I wrote the for using a while loop to show the two versions in a similar representation.
With all that said...
You're talking about a trivial difference in execution time. Use the loop that makes the code clearer and smaller, and in this circumstance that looks like foreach.
You're not resetting the "stopwatch" after the "for" test, so the time taken in the 'for' test is being added to the subsequent 'foreach' test. Also, as correctly specified, you should do an assignment inside the 'for' to mimic the exact behaviour of the foreach.
sw.Start();
foreach (var item in test)
{
}
sw.Stop();
Console.WriteLine("foreach " + sw.ElapsedMilliseconds);
sw.Restart();
for (int j = 0; j < test.Count; j++)
{
T temp = test[j];
}
sw.Stop();
Console.WriteLine("for " + sw.ElapsedMilliseconds);
sw.Reset(); // -- This bit is missing!
In your for cycle, I don't see you actually accessing items from the test. If you add var x = test[i]; into the for cycle, you'll see that the performance will be (virtually) the same.
Every access to a value-type property creates a copy, either with foreach or using indexer on the list in a for cycle.
here's a discussion on the topic Why should I use foreach instead of for (int i=0; i<length; i++) in loops?
I think that foreach provides an abstract way of looping through but it is technically slower than the for loop, a good article on the differences between the for loop and foreach can be found here
Your test is not fair. Consider how the foreach loop operates. You have the following code:
foreach (var item in test)
{
}
This creates a variable item, and on each iteration fetches the next object from the collection, and assigns it to item. This fetch and assign shouldn't create a copy, but it does take time to access the underlying collection and assign the correct value to the variable.
Then you have this code:
for (int j = 0; j < test.Count; j++)
{
}
This does not access the underlying collection at all. It does not read and assign a variable on each iteration. It simply increments an integer test.Count times, so of course it is faster. And if the compiler is smart, it will see that no operation happens in the loop and just optimize the whole thing away.
A fair comparison would replace that second bit of code with something like:
var item;
for (int j = 0; j < test.Count; j++)
{
item = test.get(j);
}
That is more comparable to what your foreach loop is doing.
As for which to use, it's really a matter of personal preference and coding style. I generally feel that foreach is more clear than for(...) from a readability standpoint.
I found only one case when it matters - Developing for Windows Phone 7. There are two reason why one should change
foreach(var item in colletion)
{
}
To
int length = array.Length;
for(int i = 0; i < length; ++i)
{
}
in XNA game if collections are big or it is called often(f.e. Update method).
It is a bit faster
less garbage
and garbage is critical, since Compact Framework GC fires every 1MB allocation, as a result, it may causes annoying freezes.
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.