This question already has answers here:
Variable scope confusion in C#
(4 answers)
Closed 9 years ago.
Is there any practical difference (speed, memory) between these two ways of declaring (introducing) variables? Which one is the better way?
Example 1:
for (int i = 0; i < myObjects.Length; i++)
{
MyObject m = myObjects[i];
}
Example 2:
MyObject m = null;
for (int i = 0; i < myObjects.Length; i++)
{
m = myObjects[i];
}
Thanks.
Example 1 makes it so that m is only "alive", in memory, within the scope of the for loop.
Example 2 makes it so that m stays occupying memory after the for loop finishes executing.
I would go with example 1, this is why:
Declaring variables inside or outside of a loop (I won't really tell you, in detail, to force you to read the link.)
Performance-wise both are compiled to the same IL, so there's no difference.
The first one is better because you are meaning to have a new object in each iteration. Also there is no need to have an object if the loop condition fails
Related
This question already has answers here:
Closures in C# - initating a thread in a function call with a value type
(3 answers)
Closed 3 years ago.
I have a problem with my multi threading app.
I have an array with 4 Threads in it.
Here is how I initialize them:
for (int i = 0; i < threads.Length; i++)
{
threads[i] = new Thread(delegate () { ThreadMethod(i); });
}
But after my first test(s) I showed that all four threads run with 3 as passed value.
I chagend it to
for (int i = 0; i < threads.Length; i++)
{
int id = i;
threads[i] = new Thread(delegate () { ThreadMethod(id); });
}
and it worked but for me it looks like there must be a better way to pass my i to my thread.
Am I right with my guess and if I am, how should I pass i?
Thank you!
The closure uses local variables -- in a for loop the variables declared for the loop are not local they have to be inside the block ({}) for that. That is why the 2nd example works.
The delegate keyword is what creates the closure and it looks for local variables to include in the closure. When it finds id it includes it. When it doesn't it references the global (outside the closure) value of i and at the time of running i has a value of 3.
This question already has answers here:
Will using 'var' affect performance?
(12 answers)
Closed 3 years ago.
I have noted in c# that using var improves your performance, especially when declaring variables of a specific class. I have done multiple bench marks and have got the same result every time. I have also read similar questions on this site and others. but no one has actually commented on this.
Can anyone please confirm or refute this.
I have a
class for image data, clsImageData
and collection clsImageDataCollection.
a function in collection class is SetCaseLowerCase().
Code is
private void SetCaseLowerCase()
{
foreach (var item in this)
{
item.DestinationImageName = item.DestinationImageName.ToLower();
}
}
Now if I use clsImageData instead of var, it performs slower, I have checked it with 100000 iterations. but results is always the same. also with other examples too.
Thanks
Edited
I have tested this simple code and got 7/10 times better performance using var. Please tell me what am I doing wrong, I am using VS 2017, debug mode for any CPU, my processor is quad core. Thanks
sw.Start();
for (int i = 0; i < 10000000; i++)
{
var xyz = "test";
}
StopClock(sw, "Example var - ");
sw.Start();
for(int i = 0; i<10000000; i++)
{
string xyx2 = "test";
}
StopClock(sw, "Example type - ");
var is compiled in a way, that makes the use of it equals to just declaring the variable/ type (except in cases it cant be done somehow else but using var ex: anonymous types). that means there are no performance changes at all. read more about var at https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/var
here is a demonstration, type the following code:
var list = new List<int>();
note that when you hover above list your IDE says:
(local variable) List<int> list
the reason for that is that var is converted to the declared type, meaning that var is actually cosmetic and its use can not impact any performance.
This question already has answers here:
Captured variable in a loop in C#
(10 answers)
Closed last month.
I have this code and do not understand why the out put is 22! I am afraid it should be 01!
can anyone explain what happens? if the list store a method with a parameter, so the parameters should be 0 and 1 respectively!
List<Action> list = new List<Action>();
for (int i = 0; i < 2; i++)
{
list.Add(() => Console.Write(i));
}
foreach (var it in list)
{
it();
}
It is Closure (1, 2).
In your case Console.Write(i) will use value of i in the moment of action call. You firstly increment i in for loop then in second loop you call every action in the list. In the moment of call of every action i has value 2 - so, you get 22 as output.
To get expected result you should create local copy of i and use it:
for (int i = 0; i < 2; i++)
{
var temp = i;
list.Add(() => Console.Write(temp));
}
Addition to Roma Doskoch's anwser, another approach is to avoid for.
var list = Enumerable
.Range(0, 2)
.Select<int, Action>(i => () => Console.Write(i));
Closures capture variables, not values.
In your code, the closure captures the variable i, not whatever value happens to be stored in i on each iteration. When you invoke the action, the variable i has a value of 2 (because the loop has finished) and therefore 2 will be printed out twice.
In order to avoid this, as other answers already point out, you need to create a new variable every time around as a workaround to not being able to capture values; if you declare a new variable on every iteration then the result of capturing the variable is equivalent to capturing the value because you won't be changing it on the next iteration.
This question already has answers here:
How can I capture the value of an outer variable inside a lambda expression?
(4 answers)
Closed 6 years ago.
What is going on here? This loop most of the time just prints this:
10101010101010101010
sometimes this:
51010101010101010101
and when i debug it, it prints in order
0123456789
class Program
{
static void Main (string[] args)
{
for ( int i = 0; i < 10; i++)
{
Task.Run(( ) => Console.Write(i));
}
Console.Read();
}
}
If you have ReSharper installed it puts a little squiggle underneath the i:
with the note:
Access to modified closure
The JetBrains site gives this explanation:
This may appear to be correct but, in actual fact, only the last value of str variable will be used whenever any button is clicked. The reason for this is that foreach unrolls into a while loop, but the iteration variable is defined outside this loop. This means that by the time you show the message box, the value of str may have already been iterated to the last value in the strings collection.
(obviously their example uses a string not an int).
It "works" under debug because other things are going on and the code isn't being executed the same as it would in release.
The solution is to use a local variable:
for ( int i = 0; i < 10; i++)
{
int local = i;
Task.Run(( ) => Console.Write(local));
}
But even then it's not guaranteed to execute in the order you expect. I just tested this and got he result:
0436215897
So each value was processed, but in indeterminate order.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Child Scope & CS0136
C# Variable Scoping
Though I have been using C# for quite some time, I have just stumbled upon this error.
If I have the following:
if(true)
{
int x = 0;
}
int x = 0;
I get an error that says: A local variable named 'x' cannot be declared in this scope because it would give a different meaning to 'x', which is already used in a child scope to denote something else.
And if I do this:
if(true)
{
int x = 0;
}
x = 0;
I get an error that says: The name 'x' does not exist in the current context.
I can understand having one or the other, but why do both of these errors exist? Is there a way around the first option? I find it very annoying.
Thanks.
Both of these errors exist to stop you from making mistakes or causing your colleagues to want to kill you.
The first fails because it's confusing to have two identically named local variables both in scope at a time.
The second fails because the variable's scope is the if statement, and you're trying to access it outside that scope.
If you want a single variable which you can use both inside and outside the block, you just need to declare it before the block:
int x;
if (true)
{
x = 0;
}
x = 0;
If you actually want two separate variables to be in scope at the same time (within the block), then give them different names - thereby avoiding later confusion.
EDIT: You can declare multiple local variables with the same name in a single method, but they have to have separate scopes. For example:
public void Foo(IEnumerable<string> values)
{
double sum = 0;
foreach (string x in values)
{
int z = x.Length;
sum += z;
}
foreach (string x in values)
{
double z = double.Parse(x);
sum += z;
}
}
Personally I don't tend to use this ability very often - at least not with different types - when the variables have meaningful names and methods are short. But it's absolutely legitimate, and can certainly be useful sometimes.
In the first case, the problem is that your int x outside the { } block has a global scope that encloses the context inside { }; therefore you are re-declaring a variable with the same name.
In the second case; x does not exist as it is only defined inside { }