I have a problem that drives me nuts. I am using a generic List that throws an ArgumentOutOfRangeException whenever I try to assign its first (or last?) index to a variable. It's a pretty large pile of code, hence I'll try to extract only the relevant stuff. So here it is:
private string GetRuleByName(string name, List<string> rules)
{
if(rules != null)
{
List<string> todo = new List<string>();
todo.AddRange(rules);
while(rules.Count != 0)
{
string r = todo[0]; // <- Error 'ArgumentOutOfRangeException' here
todo.RemoveAt(0);
// ...
}
}
}
That's how I call the method:
void treeView_AfterSelect(object sender, TreeViewEventArgs e)
{
string currentRule = GetRuleByName(treeView.SelectedNode.FullPath, ruleCollection)
// the string list "ruleCollection" always contains
// strings and thus is never empty
}
Even though it's not a very detailed presentation of what's going on, as I had to cut off a piece of some complicated code, I really hope someone else might see what produces the error.
Big thanks in advance for at least having a look!
EDIT:
This is how the method looks like. I haven't altered anything, to show what's really inside it. I hope it makes sense for somebody:
private Rule GetRuleByNameOrId(string stName, List<Rule> rules)
{
if(rules != null)
{
string searchName = stName.ToLower().Trim();
string subName = "";
int slashPos = searchName.IndexOf('/');
if(slashPos != -1)
{
if(slashPos != searchName.Length)
subName = searchName.Substring(slashPos + 1);
searchName = searchName.Substring(0, slashPos);
}
List<Rule> todo = new List<Rule>();
todo.AddRange(rules);
while(todo.Count != 0)
{
Rule r = (Rule)todo[0];
todo.RemoveAt(0);
if(r.Name.ToLower() == searchName || r.Id.ToLower() == searchName)
{
if(subName != "")
{
Rule subRule = GetRuleByNameOrId(subName, r.Children);
if(subRule != null)
return subRule;
}
else
{
return r;
}
}
if(r.Children != null && r.Children.Count != 0)
todo.AddRange(r.Children);
}//end while
}//end if(rules != null)
return null;
}
Sounds like you want the following:
private string GetRuleByName(string name, List<string> rules)
{
if(rules != null)
{
List<string> todo = new List<string>();
todo.AddRange(rules);
while(todo.Count != 0) // <-- Minor mod here
{
string r = todo[0];
todo.RemoveAt(0);
// ...
}
}
}
Otherwise you are infinitely looping on rules.Count as the size of rules is not changing
This works fine until todo is empty, then you get the exception because element 0 no longer exists as you've removed them all!
Are you sure you don't want this instead:
while(rules.Count != 0)
{
string r = rules[0]; // <- Error 'ArgumentOutOfRangeException' here
rules.RemoveAt(0);
?
The way you've written it now, you've got a loop that would actually be infinite, except that you eventually remove all the elements from the todo list, at which point you throw the exception (because in an empty list even the 0-th element doesn't exist).
Related
For some reason, my code doesn't seem to reach the last few lines.
I've added the stop point and the return point in the code.
I don't see anything wrong with the data source I use on that row whenever I check it out in debug.
The code seems to set the value there and jumps back to the top of the foreach loop.
foreach (DataGridViewRow row in dataGridView1.Rows) {
//We check if the user has already filled in some info
return point if (row.Cells[7].Value != null && row.Cells[6].Value != null && !askedTheUser)
{
//trigger for message if you want to replace them
Message m = new Message("There is already info present in the category and or size dropdown. Would you like to overwrite this?", "Overwrite", "YESNO");
if (m.Awnser) {
overwrite = true;
}
askedTheUser = true;
}
DataGridViewComboBoxCell cat = (DataGridViewComboBoxCell)row.Cells[6];
string toMatch = row.Cells[3].Value.ToString();
//Now we will start matching
//First we try to match with the package ( if that is filled in )
if (row.Cells[5].Value != null && (string)row.Cells[5].Value != "") {
toMatch = row.Cells[5].Value.ToString();
matchWithPackage = true;
}
Regex re = new Regex(#"([a-zA-Z]+)(\d+)");
Match result = re.Match(toMatch);
string alphaPart = result.Groups[1].Value;
string numberPart = result.Groups[2].Value;
Datagridview dgv = new Datagridview();
if (numberPart.Length < 4) {
numberPart = numberPart.PadLeft(4, '0');
}
#if DEBUG
Console.WriteLine(numberPart);
#endif
//Matching the category
if (CHIP != null && CHIP.Contains(alphaPart))
{
cat.Value = "CHIP";
}
else if (SOJ != null && SOJ.Contains(alphaPart))
{
cat.Value = "SOJ";
}
else if (PLCC != null && PLCC.Contains(alphaPart))
{
cat.Value = "PLCC";
}
else if (QFP != null && QFP.Contains(alphaPart))
{
cat.Value = "QFP";
}
else if (SOP != null && SOP.Contains(alphaPart))
{
cat.Value = "SOP";
}
else {
if (cat.Value != "") {
cat.Value = "";
}
cat.FlatStyle = FlatStyle.Flat;
cat.Style.BackColor = Color.DarkRed;
continue;
}
//Setting the matched color
cat.FlatStyle = FlatStyle.Flat;
cat.Style.BackColor = Color.SpringGreen;
//Adding the dropdownlist to the size cb
(row.Cells[7] as DataGridViewComboBoxCell).DataSource = dgv.AddSeconderyCombobox(dataGridView1, row.Cells[6].Value.ToString());
if (!matchWithPackage) {
continue;
}
//Matching the size
Stop Point List<string> sizeList = (List<string>)(row.Cells[7] as DataGridViewComboBoxCell).DataSource;
Doesn't reach this and beyond List<string> matchedList = sizeList.FindAll(stringToCheck => stringToCheck.Contains(numberPart));
if (matchedList.Count > 0) {
(row.Cells[7] as DataGridViewComboBoxCell).DataSource = matchedList;
}
}
So i fixt my own problem and i'm going to awnser my own question i case somebody comes across a similar problem.
if (sizeList != null) {
List<string> matchedList = sizeList.FindAll(stringToCheck => stringToCheck.Contains(numberPart));
if (matchedList.Count > 0)
{
(row.Cells[7] as DataGridViewComboBoxCell).DataSource = matchedList;
}
}
After adding the few last lines in an extra check that needed to be done I noticed that the code was being executed, but the matchedlist.count was always 0.
So what was happening is that the code after that was redundant as the matchList was 0 and the debugger just skipped jumping to these lines ( a bit confusing if you ask me ).
See the link:
http://i.imgur.com/gFcamd8.png
Notice the Autos window at the bottom shows that toParse = "". However toParse != "" evaluates as true anyway, causing the application to crash.
Here's the full method:
public void parseString(string toParse)
{
while (toParse != "")
{
string nextLine = readLine(ref toParse);
if (nextLine.IndexOf("//") == 0)
{
comments.Add(nextLine);
continue;
}
if (nextLine.IndexOf(".") == 0)
{
string[] declarationParts = nextLine.Split(' ');
string declarationString = declarationParts[0].Substring(1, declarationParts[0].Length - 1);
declarationString = char.ToUpper(declarationString[0]) + declarationString.Substring(1);
DirectiveEnum type = (DirectiveEnum)Enum.Parse(typeof(DirectiveEnum), declarationString);
string[] attributes = declarationParts.Skip(1).ToArray();
MSILNode newNode = new MSILNode(type);
newNode.addAttributes(attributes);
toParse = toParse.Trim();
if (toParse != "")
{
while (toParse[0] != '{' && toParse[0] != '.' && toParse.IndexOf("//") != 0)
{
nextLine = readLine(ref toParse);
attributes = nextLine.Split(' ');
newNode.addAttributes(attributes);
}
if (toParse[0] == '{')
{
readLine(ref toParse);
string inside = separate(ref toParse, "}");
newNode.parseString(inside);
}
}
subNodes.Add(newNode);
continue;
}
Console.WriteLine(nextLine);
}
}
It's difficult to see everything that's happening during the debugging session when only given this one snapshot. However, since toParse is passed by reference to the function readline() (line 57), it's value can be changed in the body of that function.
From the PNG image provided in the original question:
53 if (toParse != "")
54 {
55 while (toParse[0] != '{' && toParse[0] != '.' && toParse.IndexOf("//") != 0)
56 {
57 nextLine = readLine(ref toParse);
58 ...
At line 53, toParse is not empty. Then, during one of the iterations of the while loop, it is updated to an empty value. This would cause any accesses to array indices (i.e. toParse[0] in the while condition) to throw an exception.
For more information on the ref keyword in C#, see this StackOverflow issue or this official Microsoft documentation.
I hope this helps!
In the image, this line newNode.parseString(inside) is highlighted meaning that it's in the Callstack and was called before crashing. This line is probably mutating toParse to be "".
I have a search function which works good the first time i run it. When i try adding a new search the program shuts down giving me the error message:
"markerat = listBoxSökResultat.SelectedItem.ToString().ToLower(); Object reference not set to an instance of an object. NullReference.
Ive tried using if and return; but that doesnt seem to help. Anyone knows whats wrong here?
private void buttonSökNamn_Click(object sender, EventArgs e)
{
listBox1.Items.Clear();
var v = (from x in el.Descendants("recept")
where x.Element("namn").Value.ToLower().Contains(textBoxNamn.Text.ToLower())
select x);
if (v == null)
{
MessageBox.Show("Finns inte!");
return;
}
foreach (var item in v.Elements("namn"))
{
Sökresultat.Add(item.Value);
}
listBoxSökResultat.DataSource = null;
listBoxSökResultat.DataSource = Sökresultat;
}
private void listBoxSökResultat_SelectedIndexChanged(object sender, EventArgs e)
{
string markerat;
markerat = listBoxSökResultat.SelectedItem.ToString().ToLower();
if (markerat == null) return;
listBox1.Items.Clear();
if (listBoxSökResultat.SelectedItems.Count == 0) return;
var v = (from x in el.Descendants("recept")
where x.Element("namn").Value.ToLower() == markerat
select x).FirstOrDefault();
if (v == null)
{
MessageBox.Show("Finns inte!");
return;
}
textBoxNamn.Text = v.Element("namn").Value;
listBox1.Items.Add(v.Element("portioner").Value);
var test = v.DescendantsAndSelf("ingrediens").ToList();
foreach (var item in test)
{
listBox1.Items.Add(item.Value);
}
var test2 = v.DescendantsAndSelf("steg").ToList();
foreach (var item in test2)
{
listBox1.Items.Add(item.Value);
}
}
listBoxSökResultat.SelectedItem is what is null, so any further calls (.ToString()) will cause that exception. You are currently checking it's not null and SelectedItems has a count higher than 0, but after the problem occurs. By then it's too late. That defensive checking is great, but you are doing it a little too late.
SelectedItem will be null if there is no selected item at the time, so you should check that first:
if (listBoxSökResultat.SelectedItem != null)
{
markerat = listBoxSökResultat.SelectedItem.ToString().ToLower();
}
That will let you pass this particular problem.
I wasn't the one who coded this line of code, and I can't gt to understand whoever did it, why did this way on this line: res.Data.Find(itm => itm.Meta.ID.ToUpper() == i["MetaDataID"].ToString().ToUpper()).Value[i["LocaleID"].ToString()] = i["Value"].ToString();
And this line gives me a NullReferenceException. How can I get around it?
public static void LoadData(Value.Item _res)
{
DataTable Res = Connector.Run("SELECT * FROM Data WHERE ItemID='" + _res.ID + "'");
if (Res.Rows.Count != 0)
{
foreach (DataRow i in Res.Rows)
{
try
{
_res.Data.Find(itm => itm.Meta.ID.ToUpper() == i["MetaDataID"].ToString().ToUpper()).Value[i["LocaleID"].ToString()] = i["Value"].ToString();
}
catch (Exception)
{
_res.Data.Add(new Value.Data(
i["ID"].ToString(),
i["Value"].ToString(),
i["LocaleID"].ToString(),
i["MetaDataID"].ToString()
));
}
}
}
}
Thx a lot guys!!! Here is my working solution which hrows no Exceptions anymore!
public static void LoadData(Value.Item _res)
{
DataTable Res = Connector.Run("SELECT * FROM Data WHERE ItemID='" + _res.ID + "'");
if (Res.Rows.Count != 0)
{
foreach (DataRow i in Res.Rows)
{
bool _flagged = false;
var _result = _res.Data.Find(itm => itm.Meta.ID.ToUpper() == i["MetaDataID"].ToString().ToUpper());
if(_result != null && i["LocaleID"] != null)
{
if (i["Value"] == null || i["LocaleID"] == null || i["MetaDataID"] == null)
_flagged = true;
}
else
{
_flagged = true;
}
if (_flagged)
{
_res.Data.Add(new Value.Data(
i["ID"].ToString(),
i["Value"].ToString(),
i["LocaleID"].ToString(),
i["MetaDataID"].ToString()
));
}
//try
//{
// _res.Data.Find(itm => itm.Meta.ID.ToUpper() == i["MetaDataID"].ToString().ToUpper()).Value[i["LocaleID"].ToString()] = i["Value"].ToString();
//}
//catch (Exception)
//{
// _res.Data.Add(new Value.Data(
// i["ID"].ToString(),
// i["Value"].ToString(),
// i["LocaleID"].ToString(),
// i["MetaDataID"].ToString()
// ));
//}
}
}
}
Impossible to answer accurately without having the code under the debugger, however what is certain is that at least one of the following has a value of null:
_res.Data
itm.Meta
itm.Meta.ID
i["MetaDataID"]
i["LocaleID"]
i["Value"]
Old-skool debugging:
Break the statement down to it's consituent parts - using local variables. Step-through and find which one is null.
Check if one of the following are null:
i["MetaDataID"]
i["LocaleID"]
i["Value"]
if (t != null) is always null why help..
when ever i try to get value in the variable name t it always gets in the else part but i am sure that there is valuse in tat variable.
private void button3_Click(object sender, EventArgs e)
{
try
{
if (search=="")
{
}
else
{
if (textBox1.Text=="")
{
MessageBox.Show("Select A Task Or Find One");
}
else
{
search = textBox1.Text;
}
}
if (search != null)
{
t = tasks.OpenTask(search);
if (textBox2.Text!="")
{
short hour = short.Parse(textBox2.Text.Substring(0, 2));
short minute = short.Parse(textBox2.Text.Substring(3, 2));
if (t != null) // this is null dont know why
{
foreach (Trigger tr in t.Triggers)
{
if (tr is StartableTrigger)
{
(tr as StartableTrigger).StartHour = hour;
(tr as StartableTrigger).StartMinute = minute;
}
}
t.Save();
t.Close();
}
tasks.Dispose();
button2.Visible = true;
textBox3.Visible = true;
search = "";
}
else
{
MessageBox.Show("Enter Time ");
}
}
}
catch (Exception b)
{
MessageBox.Show(b.ToString());
// MessageBox.Show("Select A Task From The List ");
}
}
help guys .. well i tried it to debug but didnt get a break through..
t is null because tasks.OpenTask(search) returns null.
Probably there is no task matching your search criteria.
Why are you disposing of tasks in the first place?
Any place in your source ,where you have written something like this MyClass t = new MyClass().. where t is your class object. If you have not declared,It will always come null.
Or might be you have declared something like this
private Task t; but forgot to add new keyword. Checkout!!!