Exception thrown, when list index is a variable - c#

I have list that contains custom class elements. I want to assign one of the element's property to a variable.
The following code works:
string myVar = list[0].MyType.MyStringProperty;
However I want to repeat this process for the rest of the list, so I intend to use a loop.
This code however, does not work, as it throws an ArgumentOutOfRange exception:
for(int i=0; i<=list.Count; i++)
{
myVar = list[i].MyType.MyStringProperty;
}
How to resolve this problem?
EDIT:
The exception is thrown at the first execution of loop, at the last line. During debug, the elements in the list seem to be okay. They all have the required string type properties with values (other than null). It is possible, that it has something to do with rows, however I use this exact same method to add new rows in the code elsewhere, and it works perfectly fine (those data are not taken from lists however).
private void MyMethod(List<MyType> list)
{
for (int i = 1; i < list.Count; i++)
{
DataRow newrow = datatable.NewRow();
newrow["Column"] = list[i].MyStringProperty;
}
}

You've got a Off-by-one error in your code.
Change
for(int i=0; i <= list.Count; i++)// <=
to
for(int i=0; i < list.Count; i++)// Note <= is changed to <
Your condition is i<=list.Count which means for loop will execute when i is equal to list.Count in which case you'll get exception because List<T> is zero based.

Related

how do i count the words in a string list

I am constantly running into an overload problem,
I have looked it up but nothing seems to look like my scenario...
I was hoping that the people here could help me.
An example of my code looks as followed.
string s = textbox.text;
char[] delimiter = {' '};
string[] word = s.split(delimiter); //this gets a set of words from s.split
for (int i = 0; i <= word.length; i++) //I also tried word.count()
{
int ii = 0;
int counter = wordlist.count;
bool test1 = false;
while (test1 == false || ii != counter +1)
{
if (word[i] == wordlist[ii]) //this is where it gets stuck. It wants to load more word[i] than what there are in the list...
{
//function gets preformed
test1 = true;
}
else
{
ii++;
}
}
}
please help me, this part of my script is vital...
thank you for your time!
Shouldn't it be string[] words = s.Split(' ');
Even if we say your word is s.Split(' '); then it should be string[] words = word not string[]=word
And to count how much words are in that array just do int howManyWords = words.Length;
Also if you want to go through loop as many times as there are words in list you should do:
for(int i = 0; i < words.Lenght; i++)
{
//Do your stuff
}
While your question is very unclear (you should post what error you are getting at the least it would have made answering much easier) you cleared it up in the comments. What you are getting is an index out of range exception.
You need to change your loop
for (int i = 0; i <= word.length; i++)
To
for (int i = 0; i < word.length; i++) // preferable
or
for (int i = 0; i <= word.length - 1; i++) // not preferable
Arrays are index at 0 not 1. The length property will give you the total number of elements in the array. When you get to your last index the value of i will be greater than the number of elements because you started counting at 0.
You also need to change your while loop because you have an out of range exception happening there. Its the same problem except this time you added one to make it even worse.
while (test1 == false && ii != counter - 1)
Change it to a minus so it never goes out of range. Also change the logic to an && instead of || with the or when it finds a match it will never increment the ii so it will be stuck forever in the while.
You would also want to break out of the loop once you find the match.
Ok, so I found my problem. it was because there were no words in wordlist[] for it to read... my bad!
I should just place in a prevention method next time...
But thank you guys for your assistance! the code is now working as should!

Loop stops all code after one iteration

I have a loop which in theory should loop 40000 times but exits and doesn't continue with code after the loop, just after one iteration. I figured that I wasnt being a silly willy about the for-loops since it didn't continue after the loops at all, so that might be something with restrictions for Lists? Or mayby something about the VS-debugger that isn't working preperly? (probably not tho...)
Edit: Thanks for pointing out that the last layer was pointless. I edited the code, but the problem persists.
Edit2: To clarify, the code does not result in an exception, or breaks. It just stops without any notifications, and shows the form(since I do a windows forms application). Just... it just don't want to continue and skips the rest of the code.
for (int i = 0; i < hiddenLayerDepth - 1; i++)
{
Connectors.Add(new List<List<List<List<Connector>>>>());
for (int j = 0; j < playfieldSize; j++)
{
Connectors[i].Add(new List<List<List<Connector>>>());
for (int k = 0; k < playfieldSize; k++)
{
Connectors[i][j].Add(new List<List<Connector>>());
for (int l = 0; l < playfieldSize; l++)
{
Connectors[i][j][k][l].Add(new Connector());
}
}
}
}
hiddenLayerDepth is set to 5 when entering the loop, and playfieldSize is set to 10. It enters the innermost loop and executes the code inside, then it just stops without increasing m.
Missing
Connectors[i][j][k].Add(new List<List<Connector>>());
If you know the sizes you should just create and array up front
Well, I tried to add a 'Connector' where there were no list. The List that contained the lists that would countain the Connectors was not added.

ArgumentOutOfRangeException. But it should not be there

So I have and method like this.
var someColletion = _someService.GetSomeCollection(someParam);
var taskCollection = new Task<double>[someCollection.Count];
for (int i = 0; i < taskCollection.Length; i++)
{
// do some stuff on the i-th element of someCollection and taskCollection
// and start the i-th task
}
Task.WaitAll(taskCollection);
double total = 0;
for (int i = 0; i < taskCollection.Length; i++)
{
// get the result of each task and sum it in total variable
}
return total;
the case is when it comes into first for loop and the number of elements in both collections are suppose 1 the ArgumentOutOfRangeException is being thrown and then AggregateException is being thrown on Task.WaitAll() because the i becomes 1 (I don't know why but it does) and when it tries to access the i-th (second) element in array that contains just one element, this happens. But there is more to this. If i set a break point before first loop and go step by step then this thing does not happen. when i becomes one the cycle ends. and everything's okay. now the method I provided above is called by an ASP.NET MVC Controller's Action which itself is called Asynchronously (by ajax call) suppose 3 times. and out of this three just one executes correctly other two do the thing I said above (if not breakpointed). I think that this problem is caused by ajax call most probably because when I breakpoint it stops other calls from executing. Can anyone suggest anything ?
I suspect you're using i within the first loop, capturing it with a lambda expression or anonymous method, like this:
for (int i = 0; i < taskCollection.Length; i++)
{
taskCollection[i] = Task.Run(() => Console.WriteLine(i));
}
If that's the case, it's the variable i which is being captured - not the value of the variable for that iteration of the loop. So by the time the task actually executes, it's likely that the value of i has changed. The solution is to take a copy of the iteration variable within the loop, in a separate "new" variable, and capture that in the anonymous function instead:
for (int i = 0; i < taskCollection.Length; i++)
{
int copy = i;
taskCollection[i] = Task.Run(() => Console.WriteLine(copy));
}
That way, each task captures a separate variable, whose value never changes.

List's ForEach() method not acting as expected

Why is this not working?
List<int> test = new List<int>();
for (int i = 0; i < 20; ++i)
test.Add(i);
test.ForEach(t => t = ++t);
The elements in test are not incremented.
Firstly, List<T>.ForEach isn't part of LINQ. It's been in .NET since 2.0.
Elements in test are not incremented
No, they wouldn't be. The parameter to Action<T> is passed by value, not by reference. Changes made to the parameter (t in your case) aren't visible to the calling code - and even if they were, there's no guarantee that List<T>.ForEach would use them.
Note that if you had a reference type (e.g. StringBuilder) as the list element type, and made changes to the data in the object that the parameter value referred to, e.g.
builders.ForEach(x => x.Append("Foo"))
then those changes would be visible in the list, because they're not changes to the list at all - the list would contain the same references as before, just to objects whose data happened to have changed.
Ints are values, not references.
Plus a foreach doesn't allow manipulation of the collection elements.
So it's a double fail i'm afraid :(
What would work:
for(int i=0;i<test.Count;i++)
test[i]++;
The t variable that you have is a copy of the item in the list. You are modifying a copy, and as such the item in the list itself isn't affected. To increment each item in the list you can use a for loop:
for(int i = 0; i < test.Count;i++
test[i]++;
This is the expected result.
You wouldn't expect the following to actually increment x in Main, so your lambda example is no different.
static void Main(string[] args)
{
int x = 1;
Increment(x);
Console.WriteLine("{0}");
}
static void Increment(int x)
{
x = ++x;
}
List<int> test = new List<int>();
for (int i = 0; i < 20; ++i)
test.Add(i);
for(var z = 0 ; z < test.Count; z++)
{
test[z]++;
}

Bugs in Visual Studio 2010/Weird For-Loop behaviour?

I was just shocked when my application fired an IndexOutOfRanage exception now. I opened the Debugger Locals Pane and discovered that my integer crossed it's boundary? Basically I have something like this in my code:
string folder = Extender.GetSetting<string>("textFolder");
string mlink = folder + "\\" + filename + ".txt";
if(File.Exists(mlink))
{
string fContent = File.ReadAllText(mlink);
rtbLearnGuide.Text = fContent;
string[] strings = fContent.Split(' ');
for (int i = 0; i < strings.Length; i++, words.Enqueue(strings[i]));
}
The problem here is that i reaches the length of strings[], I have attached a picture below.
What's even more weird is that I failed to reproduce this behavior a second time.
NB: I experienced something similar earlier today with this.CreateGraphics(); My code was something like:
var dc = this.CreateGraphics();//and some other stuff
The result was that it failed to draw it even after trying to rerun like 4 times, then I went back to the code and defined dc explicitly, voila it was working. Then I changed it back to var, it was still working :/?
What might be wrong?
EDIT:
I just discovered that changing the order works. For instance:
for (int i = 0; i < strings.Length; words.Enqueue(strings[i]), i++);
doesn't fire any errors.
To answer the first part of your question, you are executing the Enqueue before the for loop's test condition. So
for (int i = 0; i < strings.Length; i++, words.Enqueue(strings[i]));
should be:
for (int i = 0; i < strings.Length; i++) words.Enqueue(strings[i]);
Basically, the "increment" portion will always execute before the "test" portion.
Format your for loop logically and you will not have that error.
for (int i = 0; i < strings.Length; i++)
words.Enqueue(strings[i]);
In your code, "i" is incremented past the condition (strings.Length) you are THEN running the word.Enqueue on an out of bounds "i".
Your loop (in pseudo code):
i = 0
Loop_Label:
IF i >= strings.Length THEN GoTo End_Label
... where the for loop body should go ...
i = i + 1
words.Enqueue strings[i]
GoTo Loop_Label
End_Label:

Categories