How to Handle the Hashtable null value? - c#

I have a problem while checking a hashtable value. In the code below I am storing 60 values in the hashtable "hash". One of the values is (or can be) Null. I am checking each entry against its corresponding entry in hashtable "hash1", to see if they match each other. If they don't match I want to check if the value in "hash" is Null, but I can't catch it - it's falling through the 'else' part). How can I overcome this problem?
if (hash[j].ToString() == "")
{
NotAnswerQuestionCount++;
}
My Code:
int ctAnsCount=0, flAnsCount=0,NotAnswerQuestionCount=0;
SqlDataAdapter sda =
new SqlDataAdapter("select quesno,[Key] from Answerkey" ,con);
DataSet ds = new DataSet();
sda.Fill(ds);
Hashtable hash = new Hashtable();
for (int i = 0; i < 60; i++)
{
hash[i+1] = ResultsListBox.Items[i].ToString();
}
Hashtable hash1 = new Hashtable();
for (int i = 0; i < 60; i++)
{
hash1[i+1] = ds.Tables[0].Rows[i][1].ToString();
}
for (int j = 1; j <=60; j++)
{
if (hash[j].ToString() != hash1[j].ToString())
{
if (hash[j].ToString() == "")
{
NotAnswerQuestionCount++;
}
//else
flAnsCount++;
}
else
{
ctAnsCount++;
}
}

Test for hash1[i] != null prior to using ToString().

You could try using if(string.IsNullOrEmpty(hash1[i])) or check for null prior to calling ToString().
if (hash[i] != null &&
hash[i].ToString() == "")
{
...

I don't think you mean null, I think you mean empty. You're checking the contents of 'hash', which looks like it is filled from a ListBox, but AFAIK a ListBox item can't be null. Also, you're checking to see if it matches the empty string ("").
How do you know that you have an empty string in the ListBox? Try Trim-ing the value before you check it (i.e. if (hash[j].ToString().Trim() == "") to catch empty strings as well as strings that only contain whitespace. Alternatively output the contents of each ListBox item to debug, bracketed by a delimiter, to check that you've actually got, like so:
foreach (Object o in ResultsListBox.Items) {
Debug.WriteLine("'" + o.ToString() + "'");
}

From C# 6 and onwards you can use the Null-conditional operator ?.
if (hash[i]?.ToString() == "") { ...

If you want to check whether a Hash Object is null or size is zero.
I think you can do like this
if (hash!= null || hash.Keys.Count==0) { blah }
Thank you.

Related

Loop based on null value of DataGridView cell

I'm still new to using c#. I searched many threads in the forum but couldn't find a solution. I would be grateful if you help.
The problem I can't solve;
If dataGridView2.Rows[i].Cells[5] value=null or empty then run the code below.
If it's full, I want it to increment [i] and move to the next line.
Loop stop point = column length of DataGridView
for (int i = 0; i < **???**; i++)
{
if (**???**)
{
TxtSayKod.Text = dataGridView2.Rows[i].Cells[2].Value.ToString() + dataGridView2.Rows[i].Cells[10].Value.ToString();
TxtHome.Text = dataGridView2.Rows[i].Cells[3].Value.ToString();
TxtAway.Text = dataGridView2.Rows[i].Cells[10].Value.ToString();
button1.PerformClick();
Thread.Sleep(3000);
btnupdate.PerformClick();
}
...
}
You can simplify looping by using a foreach-loop
foreach (DataGridViewRow row in dataGridView2.Rows)
{
if (row.Cells[5].Value is null) // Remove this: ;
{
string away = row.Cells[10].Value.ToString();
TxtSayKod.Text = row.Cells[2].Value.ToString() + away;
TxtHome.Text = row.Cells[3].Value.ToString();
TxtAway.Text = away;
button1.PerformClick();
Thread.Sleep(3000);
btnupdate.PerformClick();
}
}
Even when using a for-statement, you could assign the current row to a variable to simplify the following code:
for (int i = 0; i < dataGridView2.Rows.Count; i++)
{
var row = dataGridView2.Rows[i];
if (row.Cells[5].Value is null)
{
string away = row.Cells[10].Value.ToString();
...
}
}
Note that test is int only works if the value has been assigned to the cell as int and not say as number.ToString(). Otherwise, if it was as string, test:
if (row.Cells[3].Value is null or string { Length: 0 })
This uses a type pattern followed by a property pattern. See: Pattern Matching in C# 8.0
The semicolon (;) after your if (**???**) ; (in the unedited question) terminates the if-statement. Remove it to have to following code block to be executed as part of the if.
Do like this, run a loop for all rows and check the respective cell.
foreach (DataGridViewRow row in dataGridView2.Rows)
{
if (row.Cells[5].Value is not null && row.Cells[5].Value.ToString() == string.Empty)
{
}
}

Filtering out double quotes from a string array

I have this function right here that takes a string array and is supposed to add everything except some characters to a List.
public static void cleanUp(string[] results)
{
List<string> text = new List<string>();
for (int i = 0; i < results.Length; i++)
{
string key = results.ElementAt(i);
if (key != "\",\"" || key != "\"{\"" || key != "\"}\"" || key != "\":\"")
{
text.Add(key);
}
}
}
In the results array there are elements that look like this , and : and } etc... Why is my if statement not filtering out the special characters.
Is there something I'm missing here?
I think you want this (use String.Contains method):
List<string> text = results.Where(key => !key.Contains(',') &&
!key.Contains('{') && !key.Contains('}') &&
!key.Contains(':')).ToList();
text is a List of strings that has not that special characters.
Change the or's to && will be a good start!
if (key != "," && key != "{" && key != "}" && key != ":")
You need to use the AND (&&) operator instead of OR (||). Since you are using || , one of them always matches, and returns true. Hence, the key gets added.

Trying to compare values of a checkbox list with values of an array list c# with asp.net

We are currently programming a student information system. What we have so far is a checkboxlist that contains all the modules for the course that the selected student is enrolled on. These values are both stored in the database. What we are trying to do is have the List item values within the checkboxlist selected/ticked based upon the modules they are currently studying, based on what is stored in the database.
Here is our c# code:
string connectionString = WebConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
SqlConnection myConnection = new SqlConnection(connectionString);
myConnection.Open();
string com5 = "SELECT ModuleID FROM StudentModules WHERE StudentID = #StudentID";
SqlCommand myCommand5 = new SqlCommand(com5, myConnection);
StudentIDLabel.Text = SearchText.Text;
int StudentIDint = Convert.ToInt32(StudentIDLabel.Text);
myCommand5.Parameters.AddWithValue("#StudentID", StudentIDint);
string compareModules = myCommand5.ExecuteScalar().ToString();
var listOfStrings = new List<string>();
SqlDataReader reader = myCommand5.ExecuteReader();
while (reader.Read())
{
String currentValue = reader.ToString();
listOfStrings.Add(currentValue);
}
string[] arrayOfStrings = listOfStrings.ToArray();
foreach (ListItem li in this.CbOptional.Items)
{
for (int x = 0; x < arrayOfStrings.Length; x++)
{
if (li.Value.ToString() == arrayOfStrings[x])
{
li.Selected = true;
}
else
{
li.Selected = false;
}
}
}
From what we can see there seems to be an issue with IF statement, when comparing values from the checkbox list with values from the array.
We tested the else clause near the bottom of the above code, with "li.Selected = true" to make sure the code was running through the foreach statement correctly. All items within the checkbox list displayed as ticked. So this leads us to believe there is definitely something wrong with the IF statement inside the FOR loop.
Any ideas on this would be greatly appreciated.
Thanks
You dont need to run two for loops. You can just iterate through array and check if there is list item which is having same value as array element on specific index.
Try this.
for (int x = 0; x < arrayOfStrings.Length; x++)
{
ListItem listItemtoSelect = this.CbOptional.Items.FindByValue(arrayOfStrings[x]);
if (listItemtoSelect != null)
{
listItemtoSelect.Selected = true;
}
}
Since the List<string> will compare with the text only not value you should use this
repace li.Value with li.Text
for (int x = 0; x < arrayOfStrings.Length; x++)
{
if (li.Text.ToString() == arrayOfStrings[x])
{
li.Selected = true;
}
else
{
li.Selected = false;
}
}
In the inner loop, you are comparing the value of ListItem variable with each element in the array. Therefore, if the first element matches, the value is overwritten by the value of comparison with second element, and so on. Instead, you could try to check if the value of that particular ListItem matches any value in the list of strings retrieved from DB. You can do this like so:
if(listOfStrings.Contains(li.Value.ToString()))
{
li.Selected = true;
}
Note that you do not need to convert the listOfStrings variable to an array, the Contains method works on Lists.

Assert.AreEqual method usage in checking DataTable types

I have gone through threads given but wasn't able to find an implementation for pass case in c# (msdn website has no datatable/generic collection assert usage either)..
code at client not with us (only the 2 datatables are returned to us)
datarow dr1 = datatable1.newrow();
dr1[0] = 345;
datarow dr2 = datatable1.newrow()
dr2[0] = 345;
datatable1.rows.add(dr1); //(1)
datatable2.rows.add(dr2); //(2)
code at our end
Assert.AreEqual(dt1,dt2); //fails!!How to pass this case??
Assert.AreEqual is going to use the Equals method on the type. DataTable does not override this method, so this is a reference check. This means that dt1 is not equal to dt2.
You could use CollectionAssert, but this will do a comparison on the members. Again, DataRow does not override Equals, so it will do a reference check.
You will need to write custom comparison logic, then do something like Assert.IsTrue(DataTableComparer.AreEqual(dt1, dt2));
Your version of the AreEqual method is using Assert.AreEqual(Object expected, Object actual) . This means that it will be using Object.Equals() for the comparison.
Run this code and see what the value is:
bool areEqual = dr1.Equals(dr2);
This will return false, because they are not the same reference. Look at the documentation for Object.Equals:
If the current instance is a reference type, the Equals(Object) method tests for reference equality, and a call to the Equals(Object) method is equivalent to a call to the ReferenceEquals method. Reference equality means that the object variables that are compared refer to the same object.
You need to find a more appropriate way to compare your data. You can use a DataRowComparer to compare the values instead. You can also loop through each of your rows and compare the values yourself. See dotnetperls for an example.
AreEqual compares by reference unless object overrides the "Equals" method
Try the below, pasted from http://social.msdn.microsoft.com/Forums/vstudio/en-US/23703a85-20c7-4759-806a-fabf4e9f5be6/how-to-compare-two-datatables
Assert.IsTrue(ComareDataTables(DTable1,DTable2));
private bool CompareDataTables(DataTable DT1, DataTable DT2)
{
if ((DT1 == null) && (DT2 == null))
return true;
else if ((DT1 != null) && (DT2 != null))
{
if (DT1.Rows.Count == DT2.Rows.Count)
{
if (DT1.Columns.Count == DT2.Columns.Count)
{
for (int i = 0; i < DT1.Rows.Count; i++)
{
for(int j = 0; j<DT1.Columns.Count; j++)
{
if (DT1.Rows[i][j].ToString() != DT2.Rows[i][j].ToString())
return false;
}
}
return true;
}
else
return false;
}
else
return false;
}
else
return false;
}
I had a similar issue while developing my own CSV parsing library. I have written an assertion that throws exceptions in a way that can be used
in unit tests.
public static class AssertDataTable {
public static void AreEqual(DataTable expected, DataTable actual) {
//If both tables are null we consider them equal.
if ((expected == null) && (actual == null)) {
return;
} else if ((expected != null) && (actual != null)) {
//Check that the column count is the same
if ((expected.Columns.Count == actual.Columns.Count)) {
//Check that the column types are the same
for (int i = 0; i < expected.Columns.Count; i++) {
if (expected.Columns[i].DataType != actual.Columns[i].DataType) {
throw new Exception($"The type of of columns is not the same in both tables! Expected:{expected.Columns[i].DataType} Actual:{actual.Columns[i].DataType} for index {i}");
}
}
//Check that the headers are the same
for (int i = 0; i < expected.Columns.Count; i++) {
if (expected.Columns[i].ColumnName != actual.Columns[i].ColumnName) {
throw new Exception($"Column names do not match! Expected:{expected.Columns[i].ColumnName} Actual:{actual.Columns[i].ColumnName} for index {i}");
}
}
} else {
throw new Exception("Tables do not have the same number of columns");
}
//Up to this point we have verified the columns. Now we are going th verify the rows
//Just verify the values. Types have already been verified through the column checks.
if (expected.Rows.Count == actual.Rows.Count) {
for (int i = 0; i < expected.Columns.Count; i++) {
for (int j = 0; j < expected.Rows.Count; j++) {
if (!expected.Rows[j][i].Equals(actual.Rows[j][i])) {
throw new Exception($"Cells are not equal! In Row {j} and Column {i} Expected {expected.Rows[j][i]} Actual {actual.Rows[j][i]}");
}
}
}
return;
} else {
throw new Exception($"Rows count is not equal! Expected{expected.Rows.Count} Actual {actual.Rows.Count}");
}
} else {
//Give more information to the user.
if (expected == null) {
throw new Exception("Expected table is null! But Actual table is not.");
}
if (actual == null) {
throw new Exception("Actual table is null! But expected table is not.");
}
}
} //End of Compare Data Datatables
} //End of class
I have also taken account the suggetions made by Servy and gunr2171.
The code can also be found on the relevant Github Repo
This way I can use this method in a unit test as follows:
[TestMethod]
public void SingleTest() {
//Arrange
DataTable expected = new DataTable();
//Build my table here
//Act
DataTable actual = CustomMethodToTest();
//Assert
AssertDataTable.AreEqual(expected, actual);
}
I post this in the hopes that this post may help anyone in the future.

DataTable.Select() Property: Giving Index Out of Bound Exception

I'm trying to select only those rows which have Parent ID = 0
int predecessor = Parent;
StringBuilder valuePath = new StringBuilder();
valuePath.Append(Parent.ToString());
DataRow[] drPar;
while (true)
{
drPar = dt.Select("MenuID=" + predecessor);
if (drPar != null)
{
if (drPar[0]["ParentID"].ToString().Equals("0"))
break;
}
drPar[0]["ParentID"].ToString().Equals("0") is giving me
Out of Bound exception ..
Help Please !
DataTable.Select does not return null when there's no matching DataRow but an array with Length==0.
But apart from that, why are you using an "infinite" loop for only one statement?
So this should work:
drPar = dt.Select("MenuID=" + predecessor);
if (drPar.Length != 0)
{
if (drPar[0]["ParentID"].ToString().Equals("0"))
{
// ...
}
}
The array drPar must be empty to give this error as it is the only index you use in your code.
Try
if (drPar != null && drPar.Length > 0)

Categories

Resources