Why am I getting this exception - c#

I have a System.Data.DataSet and 1 single table in it. The table has many columns.
In a certain event handler, I am setting a decimal value for one of the fields, in a data row which is already existing (at the time of setting).
In a very rare case, I am getting a ArgumentOutOfRangeException exception.
Message: System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
Call Stack:
at System.ThrowHelper.ThrowArgumentOutOfRangeException()
at System.Collections.Generic.List`1.get_Item(Int32 index)
at System.Data.RecordManager.NewRecordBase()
at System.Data.DataTable.NewRecord(Int32 sourceRecord)
at System.Data.DataRow.BeginEditInternal()
at System.Data.DataRow.set_Item(DataColumn column, Object value)
at CPITS.Data.OrdersRow.set_ExecutionPrice(Decimal value)
Strange thing is, this is happening from the code which the framework has generated (Of course, I didn't write the Setter for the DataColumn).
Can you please help me understand & fix this problem?
EDIT
Below is the code where I am setting value:
void ibclient_OrderStatus(object sender, OrderStatusEventArgs e)
{
Data.OrdersRow drOrders = data.Orders.FindByOrderId(e.OrderId);
if (drOrders != null)
{
drOrders.FilledQuantity = e.Filled;
drOrders.ExecutionPrice = e.AverageFillPrice; //Sporadic Exception when setting a decimal value
}
}

Here is de decompiled code of RecordManager.NewRecordBase
internal int NewRecordBase()
{
int num;
if (this.freeRecordList.Count != 0)
{
num = this.freeRecordList[this.freeRecordList.Count - 1];
this.freeRecordList.RemoveAt(this.freeRecordList.Count - 1);
}
else
{
if (this.lastFreeRecord >= this.recordCapacity)
this.GrowRecordCapacity();
num = this.lastFreeRecord;
++this.lastFreeRecord;
}
return num;
}
as you can see, the only case where you could have a "index out of bounds" exception is here:
num = this.freeRecordList[this.freeRecordList.Count - 1];
since there DataTable is not thread safe, we could easily imagine a scenario where a record is removed by another thread before accessing the freeRecordList[..] but after having accessed to this.freeRecordList.Count.
In this case, freeRecordList.Count would have changed in the meanwhile => index out of bounds exception.
Thus, if I were you, I would try to find a concurrency issue (the fact that it happens in rare cases is another argument !)

Check the number of decimal places you are allowing in your table and check how many decimals the number you are committing has.
This exception can be thrown if the number of decimals is out of range.

DataTable.GetErrors Method
Gets an array of DataRow objects that contain errors.

Related

ArgumentOutOfRange In List

I have a Unity3D Project. In this project I'm supposed to add some data to a list in a specific index number but it throws me the following error:
ArgumentOutOfRangeException: Argument is out of range. Parameter name:
index
This is my code:
foreach (var Player in PhotonNetwork.PlayerList)
{
NameList.Clear();
if ((int)Player.CustomProperties["GameCount"] == First)
{
NameList.Insert(0 ,(string)PhotonNetwork.LocalPlayer.CustomProperties["Name"]);
}
else if ((int)PhotonNetwork.LocalPlayer.CustomProperties["GameCount"] == Second)
{
NameList.Insert(1 ,(string)Player.CustomProperties["Name"]);
}
else if ((int)Player.CustomProperties["GameCount"] == Third)
{
NameList.Insert(2,(string)PhotonNetwork.LocalPlayer.CustomProperties["Name"]);
}
else if ((int)Player.CustomProperties["GameCount"] == Fourth)
{
NameList.Insert(3, (string)PhotonNetwork.LocalPlayer.CustomProperties["Name"]);
}
}
The Insert method looks as this: public void Insert (int index, T item);.
And exception is thrown in two scenarios, as MSDN states in the part about ArgumentOutOfRangeException:
Parameter index is less than 0.
Parameter index is greater than Count.
The first option is not true about your case as you have all your indexes higher than zero. Then it means that in one of your else if's you try to insert a value in position far above the number of existing elements, this causes the exception.
What I can advice you is to make some debugging and look when you have less elements. Or to use Add instead of Insert, more info you can find here.
UPDATE
As an example, when you are trying to perform
NameList.Insert(3, (string)PhotonNetwork.LocalPlayer.CustomProperties["Name"]);
you are trying to insert an element to position 3, but if you have only 1 element in List then your insert throws an error.
If you First element(0) no Insert but Insert second element(1) that argument is out of range. Example: If the program executes first:
NameList.Insert(2,(string)PhotonNetwork.LocalPlayer.CustomProperties["Name"]);
But no executes:
NameList.Insert(0 ,(string)PhotonNetwork.LocalPlayer.CustomProperties["Name"]);

Index out of range using lists and for loop

I have this loop here, which for each question it is supposed to create, it generates and then formats a 'worded question' from an array of questions, such as; 'What is the sum of {0} + {1}?'. This loop then formats it, adds the worded question and the answer to an array.
// Use for loop to create the correct amount of questions
for (int i = 0; i < Data.Questions.numQuestions; i++)
{
Random rnd = new Random();
Data.Questions.Sum sum = new Data.Questions.Sum();
// Create part one and part two of the question using random numbers
// ex. 3 + 5
// 3 = partOne, 5 = partTwo
int partOne = rnd.Next(Data.Questions.Sum.min, Data.Questions.Sum.max);
int partTwo = rnd.Next(Data.Questions.Sum.min, Data.Questions.Sum.max);
// Randomly select one of the word questions
string fullQuestion = Data.Questions.Sum.wordedQuestions[rnd.Next(0, Data.Questions.Sum.wordedQuestions.Length)];
// Format the string with the generated numbers
fullQuestion = string.Format(fullQuestion, partOne, partTwo);
// Set out-of-class variables to be displayed to the user
Data.Questions.Sum.questions[i] = fullQuestion;
Data.Questions.Sum.answers[i] = partOne + partTwo;
}
Both Data.Questions.Sum.questions and Data.Questions.Sum.answers are List<string>'s and List<int>'s.
However, when this loop is run, with i = 0, I am thrown;
System.ArgumentOutOfRangeException: 'Index was out of range. Must be
non-negative and less than the size of the collection. Parameter name:
index'
Does anyone know what I'm doing wrong? As far as I know lists are dynamic, and I've defined like this;
// Arrays containing all questions and answers
// used to display questions and check answers
public static List<string> questions = new List<string>();
public static List<int> answers = new List<int>();
Also, to clarify, I do not want to use .Add(), as I have a settings panel which when you hit apply, re-runs this loop so the questions are up to date to the current settings. I need the loop to override the previous values.
Edit:
When using arrays, the better option here, I get;
System.IndexOutOfRangeException: 'Index was outside the bounds of the array.'
On assigning Data.Questions.Sum.answers[i], after assigning the array like so; public static int[] answers {};
If you can't .Add() in this lists - create a copy of this lists and .Add() there. Lists has special for that kind of thing: new List<T>(IEnumerable<T>)
If you need to dynamically scale the collection, but you also need to iterate over it multiple times, then you'll need to check whether it is large enough to either insert, or just update.
You can do this with an extension method such as this...
public static class ListExtentions
{
public static void AddOrUpdate<T>(this List<T> that, int index, T value)
{
if (that.Count > index)
{
that[index] = value;
}
else
{
that.Add(value);
}
}
}
...which can then be called like this...
list.AddOrUpdate(index, value);
...however you can make things easier for yourself if you know how many questions you are going to have to start with.
If the number of questions changes when your UI changes, then you will also have to deal with the issue have scaling down the collection to ensure old elements are removed, which is much simpler if you just re-instantiate the collections every time you need to regenerate the questions / answers.
This is likly to be cause of your problem,(I have asked for clarification in comments where you didn't reply).
Still putting this as an answer, as it is potential error spot and you need to fix this.
As you mentioned you are facing this exception on i=0. there are high chanced that this is every time case not any specific case.
If Data.Questions.Sum.questions is empty then, Data.Questions.Sum.questions[i] = fullQuestion; , will surely throw such exception. Same way for Data.Questions.Sum.answers too.
In such case, you must use .Add() to insert into list.
so your code should be,
if (Data.Questions.Sum.questions.Count > i)
Data.Questions.Sum.questions[i] = fullQuestion;
else
Data.Questions.Sum.questions.Add(fullQuestion);
But if they are not empty, it must not be the cause of this exception.
One more thing i have noticed in your code is Data.Questions.Sum.wordedQuestions.
Even if you have valid list (here Data.Questions.Sum.wordedQuestions) - as you have Length prop, it must be Array not list.
If it is empty, while doing this
string fullQuestion = Data.Questions.Sum.wordedQuestions[rnd.Next(0, Data.Questions.Sum.wordedQuestions.Length)];
this line will surely throw
An unhandled exception of type 'System.ArgumentOutOfRangeException' occurred in mscorlib.dll
as you are trying to get 0th index's data from it.
So before fetching data from list or array, first you need to check if it does have data init, and also it does have that index which you are asking.
something like
string fullQuestion = string.Empty;
if (Data.Questions.Sum.wordedQuestions != null &&
Data.Questions.Sum.wordedQuestions.Length > 0)
{
//here the way you are creating random number,
// you are assured about index is present in array.
int indexForWordedQuestion = rnd.Next(0, Data.Questions.Sum.wordedQuestions.Length);
fullQuestion = Data.Questions.Sum.wordedQuestions[indexForWordedQuestion];
}

Stackoverflow only with very large ArrayLists

I'm using a recursive version of the insertion sort algorithm to sort 5000 objects based upon a randomly generated integer property, but I've been getting a stackoverflow exception only at an ArrayList of this size while working fine for ArrayLists of other sizes.
I used Console.WriteLine to see what the "position" integer goes up to in one of my methods and it ends up at `4719 before skipping a line and giving a stackoverflow exception. How should I get around this?
I should also mention that when testing an iterative version of insertion sort in the same Visual Studio solution and using an ArrayList of the same size of objects I do not get a stackoverflow exception.
My code for the recursive insertion sort is below (AL is the ArrayList):
public void IS()
{
ISRM(0);
}
private void ISRM(int position)
{
if (position == AL.Count)
return;
Console.WriteLine(position);
int PositionNext = position + 1;
ISRMNext(position, PositionNext);
ISRM(position + 1);
}
private void ISRMNext(int position, int PositionNext)
{
if ((PositionNext == 0) || (PositionNext == AL.Count))
return;
Webpage EntryNext = (Webpage)AL[PositionNext];
Webpage EntryBefore = (Webpage)AL[PositionNext - 1];
if (EntryBefore.getVisitCount() < EntryNext.getVisitCount())
{
Webpage temp = EntryBefore;
AL[PositionNext - 1] = AL[PositionNext];
AL[PositionNext] = temp;
}
ISRMNext(position, PositionNext - 1);
}
Well, first of all, sorting through recursive call is a bad idea for several reasons.
As you've already found out, this easily leads to a stack overflow due to limited size of the stack.
It will have poor performance by definition since function call and accompanying allocation of local function context on the stack is much more expensive operation compared to something like while or for operators iterating through plain collection.
These are two reasons why #Zer0 probably suggested it, but there's more to it.
There's ready ArrayList.Sort() method waiting for you that takes custom comparator. All you need is to write said comparator for your custom objects according to whatever rules you want and call Sort(your_comparator). That's it. You do not need to re-invent the wheel implementing your own sorting method itself - unless implementing sorting method is the actual goal of your program... but I honestly doubt it.
So, It could be something like this (not tested!):
class MyComparer : IComparer
{
public int Compare(object x, object y)
{
var _x = ((Webpage) x).getVisitCount();
var _y = ((Webpage) y).getVisitCount();
if (_x < _y)
{
return -1;
}
if (_x > _y)
{
return 1;
}
return 0;
}
}
Usage:
var myAL = new ArrayList();
// ... filling up the myAL
myAL.Sort(new MyComparer());

ArgumentException in Tablets.Count method

sistematically, but only on one PC, while executing this code:
using Microsoft.Ink;
...
Tablets allTablets = new Tablets();
int numTablet = allTablets.Count;
I get this exception.
System.ArgumentException: Valore non compreso nell'intervallo previsto. {In English --> Value not in the right range}
in Microsoft.Ink.InkTabletsClass.get_Count()
in Microsoft.Ink.Tablets.get_Count()
How could a COUNT throw this kind of exception?
Does it means that the Count method return a value that is not int?
Thanks.
How could a COUNT throw this kind of exception?
Because of some logic that is implemented in the getter of the Count property of the Tablets class. It is in the getter that the exception is thrown.
Does it means that the Count method return a value that is not int?
No. An int property can only return an int value or throw an exception. It can never return a value of any other type. The compiler enforces this.
I tried your code, and it works for me. That being said, I have encountered similar exceptions so many times before that I now make it a habit to check for null objects first. So, I would use:
Tablets allTablets = new Tablets();
int numTablet = 0;
if (allTablets != null)
numTablet = allTablets.Count;
To answer your question, for some reason new Tablets() returns null instead of an empty ICollection.

Error when checking length of a string. Index and length must refer to a location within the string. Parameter name: length

Note: I am not using substring.
Why would this cause the index and length location error? Note: Specifically, the piece which causes it is the if statement which checks the length of PONumber --- which btw: at the time of execution has a value who's length is 11 characters.
[StringLength(41)]
private string _EXTENDEDDESCRIPTION;
public string EXTENDEDDESCRIPTION
{
get { return _EXTENDEDDESCRIPTION; }
set { _EXTENDEDDESCRIPTION = value; }
}
public string PONumber { get; set; }
//Note, this is embedded inside a save method for the class
if ((this.EXTENDEDDESCRIPTION ?? string.Empty) == string.Empty)
{
if (this.PONumber.Length <= 41)
{
this.EXTENDEDDESCRIPTION = this.PONumber;
}
}
Causes this error:
Index and length must refer to a location within the string.
Parameter name: length
System.ArgumentOutOfRangeException: Index and length must refer to a location within the string.
Parameter name: length
at System.String.InternalSubStringWithChecks(Int32 startIndex, Int32 length, Boolean fAlwaysCopy)
Unfortunately, i cannot replicate this issue when debugging locally and I have to rely on logging to tell me what / if anything is different on production. But, I know the PONumber has a length. It is a non-nullable string. It should return at least 0. In my production situation it has a length of 11, which if I remove the if statement and just let EXTENDEDDESCRIPTION get set regardless, it gets the 11 character value from PONumber.
You stated that you are not using substring, but that function (InternalSubStringWithChecks) is only called by Substring in all the framework (take a decompiler and look at it, it's only called by Substring).
Maybe it's not your code the one which throws the exceptions, you are missing the full stack trace (at least is not posted here, how are you sure that's the piece of code generating the exception?), maybe digging a bit more in the stack can shed some light.

Categories