ArgumentNullException in an array that I can't figure out - c#

I have been up half the night and still trying to get this null exception figured out. I have read a few of texts about this issue but none has helped me in any way, to me what the problem is as it should work :/ It just crashes at this piece of code:
Private void UpdateGUI()
{
string selectedItem = cmbDisplayOptions.Items[cmbDisplayOptions.SelectedIndex].ToString();
rdbtReserv.Checked = true;
lstReservations.Items.Clear();
lstReservations.Items.AddRange(m_seatMngr.GetSeatInfoStrings(selectedItem));
}
lstReservations.Items.AddRange(m_seatMngr.GetSeatInfoStrings(selectedItem)); Gives me the ArgumentNullExeption, but to me it should not do that.
the addrange sends string selectedItem to another class:
public string[] GetSeatInfoStrings(string selectedItem)
{
int count = GetNumOfSeats(selectedItem);
if (count <= 0)
{
return null;
}
string[] strSeatInfoStrings = new string[count];
for (int index = 0; index <= m_totNumOfSeats - 1; index++)
{
strSeatInfoStrings[index] = GetSeatInfoAt(index);
}
return strSeatInfoStrings;
}
This int count = GetNumOfSeats(selectedItem); goes to here and returns with an int:
private int GetNumOfSeats(string selectedItem)
{
if (selectedItem == "ReservedSeats")
{
return GetNumReserved();
}
if (selectedItem == "VacantSeats")
{
return GetNumVacant();
}
else
{
return m_totNumOfSeats;
}
}
I have checked the arrayed have the correct number of spaces(60) and that selectedItem has a string(Allseats to start with so it should return m_totnumOfSeats which is an int of 60) But then in the private int GetNumOfSeats something goes wrong and it returns null and...well why?
I can't see the problem.. maybe gone blind by trying to find the issue. Always got outstanding help here and I have learned tons!! So maybe someone can point out all the issues there is in my code.
Thanks a million in advance for any and all advice!
//Regards

Check if your variables are actually initialized and returns correct values.
There are logical errors in the GetSeatInfoStrings methods and the GetNumofSeats method.
Lucky for you the GetNumOfSeats method will always return 60 for you because of the wrong way you compare strings. It's not the right way, so use the Equals method for comparison like
if (selectedItem.Equals("ReservedSeats"))
With that you will get a proper output form GetNumOfSeats(string) method.
The next thing is to fix your looping in the GetSeatInfoStrings method so as to not get an array index out of bounds exception like this.
string[] strSeatInfoStrings = new string[count];
for (int index = 0; index <= count; index++)
{
strSeatInfoStrings[index] = GetSeatInfoAt(index);
}
return strSeatInfoStrings;
Also fix the part where your logic returns a null in the GetSeatInfoStrings method. it should return an empty string array according to your logic as
return new string[0];
That should probably get your methods working. You need to be very careful of what you code before you debug it :-)

Looking at the source code of ObjectCollection, when you call AddRange and pass a null value, you get back the ArgumentNullException.
You could prevent this changing this code
if (count <= 0)
{
return new string[0];
}

Related

Replace if else statement with a single method containing a conditiion

I am still learning C# but I've been on annual leave and I have come back to work and seen this piece of code my senior has left me before he went on his annual leave:
public string GetBasketTotalPrice(string basketLocation)
{
var basketTotalPrice = _driver.FindElements(CommonPageElements.BasketTotalPrice);
if (basketLocation.ToLower() == "top")
return basketTotalPrice[0].Text.Replace("£", "");
else
return basketTotalPrice[1].Text.Replace("£", "");
}
private int GetElementIndexForBasketLocation(string basketLocation)
{
return basketLocation == "top" ? 0 : 1;
}
I am assuming instead of using the if else statement, he wants me to use his new method of GetElementIndexForBasketLocation.
My question is simply how to implement this change?
Thanks
It's not totally clear what you're looking for, but you can rework the code something like this:
public string GetBasketTotalPrice(string basketLocation)
{
var basketTotalPrice = _driver.FindElements(CommonPageElements.BasketTotalPrice);
int index = GetElementIndexForBasketLocation(basketLocation);
return basketTotalPrice[index].Text.Replace("£", "");
}
private int GetElementIndexForBasketLocation(string basketLocation)
{
return basketLocation.ToLower() == "top" ? 0 : 1;
}
It looks like the method he provided you isn't calling ToLower(), leaving it to the client to do that work, which could lead to mistakes down the road.
Also, you might consider using string.Equals with StringComparison.OrdinalIgnoreCase instead of ToLower.
And it might be a good idea to add a null check before trying to call a method on the string, so you can throw an ArgumentNullException instead of the NullReferenceException that the current code will throw.
public string GetBasketTotalPrice(string basketLocation)
{
var basketTotalPrice = _driver.FindElements(CommonPageElements.BasketTotalPrice);
return basketTotalPrice[GetElementIndexForBasketLocation(basketLocation)]
.Text.Replace("£", "");
}
private int GetElementIndexForBasketLocation(string basketLocation)
{
if (basketLocation == null) throw new ArgumentNullException(nameof(basketLocation));
return basketLocation.Equals("top", StringComparison.OrdinalIgnoreCase) ? 0 : 1;
}

going through a list with a for loop

Okay, i have a list and where i have structs stored, and i need to go through them from the last to the first, to check if one of the variables in the struct is 1. the code look like this:
for(int i = (checkpoints.Count - 1); i == 0; i--)
{
if(checkpoints[i].active == 1)
{
playerPositionX = checkpoints[i].xPosition;
playerPositionY = checkpoints[i].yPosition;
camPositionX = checkpoints[i].xPosition;
break;
}
}
this is the struct that i use:
private struct checkpoint
{
public int xPosition;
public int yPosition;
public int active;
}
what i need to do is to check if the variable active is == 1 in the struct that i have stored in the list. i have around 3-8 structs stored in the list. I need to start the check from the last struct in the list and work my way to the first.
when i try to debug the program it looks like it's not going from the last, but it starts at i=0.
please leave a comment if you have a fix, or if you need more information.
You can also use LastOrDefault() function. But, here can be one problem, because we are searching for Struct.
If nothing found?
LastOrDefault() will return default(checkpoint) if nothing found. The default value of a struct is the struct with all its values in turn default initialized. So, we must cast them to nullable using .Cast<checkpoint?>.
var activeCheckPoint = checkpoints
.Where(x => x.active == 1)
.Cast<checkpoint?>()
.LastOrDefault();
Or we must do the second check afterward that the returned object's active value is 1.
var activeCheckPoint = checkpoints.LastOrDefault(x => x.active == 1);
if(actactiveCheckPoint.active == 1)
{
// Then it is Ok
}
else
{
// Nothins was found
}
But, if you want to use for loop, then you must change i == 0 to i >= 0.
Your mistake was that you said to go though the loop if i was equal to 0, when it wasn't. You want the loop to loop until i is greater or equal to zero.
for(int i = (checkpoints.Count - 1); i >= 0; i--) // your mistake was here
{
if(checkpoints[i].active == 1)
{
playerPositionX = checkpoints[i].xPosition;
playerPositionY = checkpoints[i].yPosition;
camPositionX = checkpoints[i].xPosition;
break;
}
}

How to pass the List<String> value as String to the Other function

I have a List<> as lsSplitMember I am sending it through the while loop to the function
as a string.But it throws exception message "Index was out of range. Must be non-negative and less than the size of the collection".
I have tried with the below code .
//Globally declared variable lsSplitMember
List<String> lsSplitMember=new List<String>();
int ic = lsSplitMember.Count();
while (ic != 0)
{
Process_Split(lsSplitMember[ic]);
ic--;
}
Protected void Process_Split(String Member)
{
//Some Code
}
So how can I Solve this problem?
int ic = lsSplitMember.Count();
while (ic != 0)
{
Process_Split(lsSplitMember[ic-1]); // your index was off-by-one
ic--;
}
Please note that using the C# language features, that's a lot of unnecessary meta-code:
foreach(var text in lsSplitMember)
{
Process_Split(text);
}
This is a lot easier to read and way less error prone to write. If you need the list to be processes upside down, you can reverse it first.
The count is one greater than the last index of the List since they are zero-indexed, and this is the index you try to access. Really, you should use an iterator for this:
foreach( string s in lsSplitMember )
Process_Split( s );
Try this...
Change Process_Split(lsSplitMember[ic]); to Process_Split(lsSplitMember[ic-1]);
Try this
List<String> lsSplitMember=new List<String>();
int ic = lsSplitMember.Count();
while (ic != 0)
{
ic--;
Process_Split(lsSplitMember[ic]);
}
Protected void Process_Split(String Member)
{
//Some Code
}
lsSplitMember.ForEach(s =>
{
Process_Split(s);
});
Provided lsSplitMember is not null

Returning index value of list object?

for the life of me, I cannot figure this out. Basically I am trying to make a search function with an unsorted list of objects. No matter what I try, the location returns -1. When I look at the logic, it makes sense to me, but maybe I've been staring at my screen for too long. Any help would be greatly appreciated!
public static int ContactSearchFirst(List<Contact> contactList, string userInput)
{
int location = -1;
for (int index = 0; index < contactList.Count && location == -1; index++)
{
if (contactList[index].FirstName.ToUpper().Equals(userInput.ToUpper()))
{
location = index;
}
}
return location;
}
If you're using C#, then the whole loop is un-necessary. You can simply use the List<T>.FindIndex method:
public static int ContactSearchFirst(List<Contact> contactList,
string userInput)
{
return contactList
.FindIndex(c =>
c.FirstName.Equals(userInput,
StringComparison.InvariantCultureIgnoreCase));
}
You may also want to trim the input so that leading/trailing spaces don't cause unexpected results.
You would only get a new location value if the following is ever true, so maybe it never is true:
if (contactList[index].FirstName.ToUpper().Equals(userInput.ToUpper()))
Perhaps the parameters are being passed incorrectly when the function is called.
If you are using visual studio you can easily check this by setting a break point in your code and inspecting the contactList and userInput variables.

changing the value of certain elements of a list

I am looping through a list and would like to add multiple occurrences, should I find them.
so far I have,
public struct optionsSort
{
public string name;
public string date;
public double strike;
public string callPut;
public double size;
public string isin;
}
List<List<optionsSort>> stocks = new List<List<optionsSort>>();
optionsSort tempStock1 = new optionsSort();
List<optionsSort> posCheckOptions = new List<optionsSort>();
then some code, then,
for(int k = 0; k<posCheckOptions.Count; k++)
{
for(int l = 0; l<posCheckOptions[l].Count; l++)
{
if(posCheckOptions[l+1] == null)
{
//finished the iteration
break;
}
else if
(posCheckOptions[k][l + 1].date == posCheckOptions[k][l].date
&& posCheckOptions[k][l + 1].strike == posCheckOptions[k][l].strike
&& posCheckOptions[k][l + 1].callPut == posCheckOptions[k][l].callPut)
{
posCheckOptions[k][l].size = posCheckOptions[k][l].size
+ posCheckOptions[k][l + 1].size;
}
}
}
Basicly, Im looking forward from the start of the list. asking the question, are certain elements of the list at i+1 the same as i, if so, add those elements to i and delete the entire row.
i get this error
"Error 1 Cannot modify the return value of 'System.Collections.Generic.List.this[int]' because it is not a variable C:\Users\WindowsFormsApplication1\WindowsFormsApplication1\ReadCSV.cs 890 25 WindowsFormsApplication1
"
Many Thanks for looking.
I believe your problem is that you are using a mutable struct. Mutable structs are evil.
The simplest solution is to change optionsSort to a class. That should fix the error message.
To explain the error message, when you call posCheckOptions[k][l], since optionsSort is a struct, it returns a copy of the value in the list. When you change size, it will update the copy, but not the one in the list. The copy would then be discarded. The compiler recognizes this and stops you.
I recommend you read up on the differences between reference types and value types.

Categories