What is the 'ctr' variable in a parallel C# loop? [duplicate] - c#

This question already has answers here:
What does the '=>' syntax in C# mean?
(7 answers)
Closed 1 year ago.
I recently used a Parallel.For loop (see code below) in a small C# program and I'm a little perplexed by the ctr variable. Every example I've seen so far has the name of this variable set to ctr, but I cant seem to find any good resource on what it means or why exactly this name is used.
If anyone knows more about it, I would be happy to hear it!
public static int[] calcArray(int[] arrName, int arrSize, int seed)
{
Parallel.For(0, arrSize, ctr =>
{
arrName[ctr] = AllfunctionsClass.Random(seed);
seed++;
});
return arrName;
}

The current index value.. imagine a normal for loop
for (int ctr=0; ctr < arraySize; ctr++)
{
// ctr is the current value between 0 and arraySize-1
}
The variable name chosen as arbitrary in this case, probably short for counter. IMHO variable names should very rarely be abbrvted and should make it obvious what they represent e.g. arrayPosition or position or maybe index or something like that

Related

Why These two c# scripts give different results? [duplicate]

This question already has answers here:
Regarding local variable passing in Thread
(2 answers)
Closed 2 years ago.
I'm working on a big list of buttons and trying to AddListener() for every Button on this list using a quick way
the first way is
btn[0] = CHbutt[0].GetComponent<Button>(); btn[0].onClick.AddListener(delegate { CH(0); });
btn[1] = CHbutt[1].GetComponent<Button>(); btn[1].onClick.AddListener(delegate { CH(1); });
btn[2] = CHbutt[2].GetComponent<Button>(); btn[2].onClick.AddListener(delegate { CH(2); });
btn[3] = CHbutt[3].GetComponent<Button>(); btn[3].onClick.AddListener(delegate { CH(3); });
and it works very well, and AddListener() to all Buttons in btn[];
but a lot of lines...
the second way
for (int i = 0; i < CHmatt.Count; i++)
{
btn[i] = CHbutt[i].GetComponent<Button>(); btn[i].onClick.AddListener(delegate { CH(i); });
}
but this one is not working, this one AddListener() to only the last button btn[0]
I'm very curious about the difference between these two scripts.
It's a capturing issue. Change the code as follows, to avoid capturing i:
for (int i = 0; i < CHmatt.Count; i++)
{
var ii = i;
btn[i] = CHbutt[i].GetComponent<Button>();
btn[i].onClick.AddListener(delegate { CH(ii); });
}
What is being passed into AddListener function is a delegate method; however, since you're passing in a loop iteration variable i, the context is captured, and i is actually referenced. As your loop advances, the value of i changes for all captures, therefore making this approach "not work".
By introducing a local copy of i (the name is not material here, I called it ii), which goes out of scope on each loop iteration, the capture of i is avoided, and the actual value of ii is passed to the delegate method (technically, captured, but it's a copy of i for each loop iteration, and therefore does not change as i changes.)

Elegant way to implement repetition block in C# [duplicate]

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

Why does this output 333 not 0112 at Array.ForEach? [duplicate]

This question already has answers here:
Is there a reason for C#'s reuse of the variable in a foreach?
(4 answers)
Closed 8 years ago.
Why the below code ouput 333 not 012?
I think the code is so simple and I check and check and double check, triple check, can not get answer yet. Any one can help me?
Action[] tmp = new Action[3];
for (int i = 0; i < tmp.Length; i++)
{
tmp[i] = () => Console.WriteLine(i);
}
Array.ForEach(tmp, m => m());
Console.Read();
You should change your code to:
Action[] tmp = new Action[3];
for (int i = 0; i < tmp.Length; i++)
{
int j = i;
tmp[i] = () => Console.WriteLine(j);
}
Array.ForEach(tmp, m => m());
Console.Read();
The reason is closure is nest
More detailed information please see those links:
Is there a reason for C#'s reuse of the variable in a foreach?
http://ericlippert.com/2009/11/12/closing-over-the-loop-variable-considered-harmful-part-one/
This occurs because there is only one i variable in the original code as for does not introduce a new variable "each loop" and the same variable is closed over in all the closures! As such, the same (i) variable is assigned the last value (3) before any of the functions are executed after the loop.
Compare with the following code which ensures a new variable to bind in each closure (this is one rare case where I use underscores for a local variable to show "something funny" is happening):
for (int _i = 0; _i < tmp.Length; _i++)
{
int i = _i; // NEW/fresh variable, i, introduced each loop
tmp[i] = () => Console.WriteLine(i);
}
This behavior (and complaints against) is discussed in detail in Is there a reason for C#'s reuse of the variable in a foreach? - for and foreach have this same "issue" in C#4 and before, which is "fixed" for foreach in C#5.
I think it is fair to say that all regret that decision. This is one of the worst "gotchas" in C#, and we are going to take the breaking change to fix it. In C# 5 the foreach loop variable will be logically inside the body of the loop, and therefore closures will get a fresh copy every time. - Eric Lippert

C# modifying a list in a function [duplicate]

This question already has answers here:
Directly modifying List<T> elements
(6 answers)
Closed 8 years ago.
I am writing a function which is passed in a list which is partially filled. I'd like to set some of the fields within the list inside this function. I thought that passing it as a reference would allow me to do this, however, I get the following error:
Error 1 Cannot modify the return value of 'System.Collections.Generic.List.this[int]' because it is not a variable
I am wondering what I might need to do to tell C# that I wish to have the option of modifying the contents of the list.
Here is a summarized version of my code:
public static void Determine_RTMM_Descriptor(ref List<Struct_Descriptor_Type> symbols, string Dwarf_Output_Filename)
{
...
lines = System.IO.File.ReadAllLines(Dwarf_Output_Filename);
//loop on symbol names
for (int idx = 0; idx < symbols.Count; idx++)
{
if(symbols[idx].size == 0)
symbols[idx].size = (int)new System.ComponentModel.Int32Converter().ConvertFromString(split_line[DwarfInterface.SIZE_INDEX]);
...
}
Thanks in advance for any help.
The underlying issue here is that you have a list of value types. When you use the indexer of the list to get an item from the list you are getting a copy of that type. The code symbols[idx] is the value of that item. It is not a variable representing that item, as the error message is telling you.
You're trying to mutate the size of the copy, which will have no effect on the item of the list. This is such a common mistake that the compiler even makes this an error.
If you really are sure that you want to have a mutable value type (hint: you aren't, and you shouldn't have one; you almost certainly just want to have a class here to avoid this problem entirely) then you would need to get the value of the item, mutate it, and then set the item again:
if(symbols[idx].size == 0)
{
var symbol = symbols[idx];
symbol.size = 42;
symbols[idx] = symbol;
}
Your return type on the function is "void" when you should set the return type to the list. That should allow you to change it and return it modified.

Is this a Capture problem? I still can't resolve

I thought this was a capture issue but nothing I do works. try to simplify here:
foreach (Question question in Test.Questions)
{
int id= question.id;
if(someIDictionary.TryGetValue(id, out value)
{
question.answerobject.number=someinteger;
}
else
{
question.answerobject.number=someotherinteger;
}
}
I tried making a temp for question object, but still not working. all results are always last iteration value.
EDIT: Each answerobject is created within each question object as the question is created using linq to sql. then the questions are returned as an IList.
EDIT 2: The issue does not occur if I assign values to another field of question. the issue is only with the answerobject.the values of answerobject are same for all questions (the last assignment).
What is the problem you are seeing? The "capture" problem only affects async/deferred/threaded code - it shouldn't affect this case.
I wonder if the most likely problem here is that all your Question objects have the same answerobject instance - or even that you have the same Question instance lots of times.
illustration of the "capture propblem" (see comments): this is a problem seen when using a lambda/anon-method; if the iteration variable (question above) is used in the lambda/anon-method, it is "captured" - but in a slightly counter-intuitive way...
For example; we might expect this to print (in an unpredictable order) the numbers 0-9:
int[] vals = {0,1,2,3,4,5,6,7,8,9};
foreach(int i in vals) {
ThreadPool.QueueUserItem(delegate {
Console.WriteLine(i);
});
}
Console.ReadLine();
But it doesn't... we fix it by adding an extra variable:
int[] vals = {0,1,2,3,4,5,6,7,8,9};
foreach(int i in vals) {
int tmp = i;
ThreadPool.QueueUserItem(delegate {
Console.WriteLine(tmp);
});
}
Console.ReadLine();
This is because the behaviour of captured variables is determined by their lexical scope... the scope of the iteration variable is a bit larger that we would like.
The issue appears to occur when answerobject.number (int?) is assigned "Null" when the object is created. If I try to assign a value during the loop i get the issue above. If howwever I assign an integer when the object is created the problem is gone and i can then addign new values during the loop. Can you explain to me cause I dont get it.

Categories