NullReferenceException on DataRow C# [duplicate] - c#

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 7 years ago.
My problem is about an object not set to an instance after the first line inside the foreach loop. I really had a hard time thinking what should be instantiated here. So please guys, i just want to map the data from the DataTable to the a new List.
It errors out after this line,
aa.fieldParams[counter].field = row["ParameterField"].ToString();
Here is my actual code.
public class ParsedData
{
public static void ParseData(DataTable parsedData)
{
ObjectProperties aa = new ObjectProperties();
int counter = 0;
foreach (DataRow row in parsedData.Rows)
{
//parsedData.Rows = new DataTable[parsedData.Rows.Count];
aa.fieldParams[counter].field = row["ParameterField"].ToString();
aa.fieldParams[counter].parameterType = row["ParameterType"].ToString();
aa.fieldParams[counter].length = Convert.ToInt32(row["ParameterLength"]);
aa.fieldParams[counter].setIteration = Convert.ToInt32(row["NumberOfIterations"].ToString());
counter++;
}
}
}
Here is the ObjectProperties class.
public class ObjectProperties
{
public FieldParameters[] fieldParams { get; set; }
public int Counter { get; set; }
}
public class FieldParameters
{
public string field { get; set; }
public int length { get; set; }
public int setIteration { get; set; }
public string parameterType { get; set; }
}
aa.fieldParams[] do not have any values yet because the values of this will be coming from the parsedData.Rows. I am currently having the correct values on row but after the first line inside the loop it errors out.
parsedData values are coming from CSV file.

Initialize your array first:
ObjectProperties aa = new ObjectProperties();
aa.fieldParams = new FieldParameters[parsedData.Rows.Count]; //initialize your array first
You also haven't initialized your Array's elements:
foreach (DataRow row in parsedData.Rows)
{
aa.fieldParams[counter] = new YourArrayType(); //instantiate the current element
//...your code...
counter++;
}
Remember you have to instantiate every element of the array when your array contains reference type elements.

Check for null like this before using .ToString() on DataRow.
if (!(row["ParameterField"] is DBNull))
aa.fieldParams[counter].field = row["ParameterField"].ToString();
Also check for null values on other lines before casting.

You are using aa.fieldParams but I only see aa declared and initialized. What about fieldParams? Do you need to initialize it? Can you post the code for ObjectProperties class to see what does fieldParams hold?
May be aa.fieldParams is null[counter]?
Also if you do not trust the Column names in the DataRow then better check if the column with that name exists in the datatable before trying to access it.
Thanks,

Related

Fastest way of comparing two lists without using nested loops

I have two types:
public class SubCategories
{
public static List<SubCategories> subCategories = new List<SubCategories>();
public string title { get; set; }
public string IDfromCategories { get; set; }
public string subCategoryID { get; set; }
public bool isChecked { get; set; }
}
public class UserInsideCategories
{
public string userEmail { get; set; }
public string iDfromSubCategories { get; set; }
}
And two lists both containing this object multiple times.
Now I wanna go through a list with type SubCategories and check each object, if it contains the same value as my other list of type UserInsideCategories. Specifically, I wanna know if any object on the list.SubcategoryID is equal to any object on the other list.IdFromSubCateogires.
I achieved this like so:
List<SubCategories> branch = new List<SubCategories>();
for(int i = 0; i < subCategories.Count; i++)
{
SubCategories e = new SubCategories();
for(int x = 0; x < allSubs.Count; x++)
{
if (e.IDfromCategories == allSubs[x].iDfromSubCategories)
e.isChecked = true;
}
branch.Add(e);
}
So I am using a nested loop. But since I have to do this multiple times, it takes far too long.
I also thought about turning all values from SubCategories into a simple string array and use the Contains function, to see if the current object.IDfromCategories contains the object on the array. This would mean I would NOT use a for loop. But interenally, I believe, the system is still using a loop and therefore there would be no performance benefit.
What would be the best way of checking each object if it contains a value from the other list?
You should use some kind of lookup table. Probably either HashSet or Dictionary. The former only allows checking if a key exists in the set, while the later allows you to also find the object the key belongs to.
To check all the UserInsideCategories that shares an id with a SubCategories you could write:
var dict = subCategoriesList.ToDictionary(s => s.subCategoryID, s => s);
var matches = userInsideCategoriesList.Where(l => dict.ContainsKey(l.iDfromSubCategories));
if you want matching pairs you could write:
foreach (var user in userInsideCategoriesList)
{
if (dict.TryGetValue(user.iDfromSubCategories, out var subCategory))
{
// Handle matched pairs
}
}
This assumes that the ID is unique in respective list. If you have duplicates you would need something like a multi-value dictionary. There are no multi-value dictionary built in, but I would expect there are some implementations if you search around a bit.

Static vs Non-Static Classes

This is what my code looks like in my public Form1()
while (accessReader.Read())
{
for (int i = 0; i < count; i++)
{
string urlpart2= accessReader.GetValue(i).ToString();
WebRequest request = WebRequest.Create("urlpart1" + urlpart2+ "urlpart3");
string json;
var response = request.GetResponse();
request.ContentType = "application/json; charset=utf-8";
using (var streamr = new StreamReader(response.GetResponseStream()))
{
json = streamr.ReadToEnd();
List<MyObject> list = JsonConvert.DeserializeObject<List<MyObject>>(json);
var date = MyObject.Start;
//MessageBox.Show(date.ToString());
This is my class representing the different variables my json string returns
public class MyObject
{
public int Type { get; set; }
public string Country { get; set; }
public string Channel { get; set; }
public string Code { get; set; }
public DateTime Start { get; set; }
public DateTime End { get; set; }
}
This is what a json string will return, the only difference that will change is maybe type, code, start, and end. - I want the Start and End Values.
[{"Type":1,"Country":"CA","Channel":"","Code":"1EZ","Start":"2014-10-24T00:00:00","End":"2015-10-23T00:00:00"},{"Type":2,"Country":"","Channel":"","Code":"UAD","Start":"2014-10-24T00:00:00","End":"2017-10-23T00:00:00"},{"Type":2,"Country":"","Channel":"","Code":"TPQ","Start":"2014-10-24T00:00:00","End":"2017-10-23T00:00:00"},{"Type":3,"Country":"","Channel":"","Code":"SVC_PRIORITY","Start":"2014-10-24T00:00:00","End":"2017-10-23T00:00:00"}]
I am fairly new to programming and I have run into an error I do not really understand 'An object reference is required for the nonstatic field, method, or property'.
Also I created this class within my Form1.cs as opposed to creating a new class in my Project Solution (if that matters?)
You try to access MyObject.Start like it would be a static property or field. However it's a instance field and basically you need to get a instance to access the field.
MyObject obj = list[0];
var date = obj.Start;
The field List<MyObject> list = ... contains all data which got deserialized from the json file ( And none if no data exists in the json file! ).
I guess you want to access all data of the json file, in this case i would prefer iterating through the objects via a foreach loop.
foreach (MyObject item in list) { .... }
The problem is with line var date = MyObject.Start; You have created a list of MyObjects. To access them you have to use list indexes i.e. var first = list[0] returns first element. Then you can get required date as: first.Start
In order to process every entry of your list you can use foreach loop as follows:
foreach (var obj in list) {
// use obj.Start, obj.End values
}

I cannot create object that contains arrays of property inside object

I am a new developer to c# MVC3.
I have a problem that I cannot create object that contains arrays of property inside object.
For example, I want to create instance ABC.Property[] for 10 arrays.
ABC.Property[0]
ABC.Property[1]
ABC.Property[2]
.....
....
ABC.Property[10]
I used debug mode to check and found out that ABC.Property[] is null. So i cannot add the value back to that object's array.
How to crate object with propeties's array?
thank you.
namespace finance3.Models
{
public class Expected_and_Risk
{
public decimal[] Prop { get; set; }
public decimal[] Forecast { get; set; }
public string[] Name { get; set; }
public decimal[] AxB { get; set; }
public decimal[] PowAxB { get; set; }
public decimal ExpectValue(Expected_and_Risk abc)
{
decimal count = abc.Forecast.Count();
Expected_and_Risk Result = new Expected_and_Risk();
for (int i = 0 ; i < count ; i++)
{
// here is the problem
// i cannot add new data to array because it has no dimemsion and i tried this
//
// Expected_and_Risk[] Result = new Expected_and_Risk[10];
//
// but it didn't work
Result.Name[i] = abc.Name[i];
Result.Prop[i] = abc.Prop[i];
Result.Forecast[i] = abc.Forecast[i];
Result.AxB[i] = abc.Prop[i] * abc.Forecast[i];
decimal a = Result.AxB[i];
decimal sumAxB =+ a;
double temp = (double)(a * a) ;
Result.PowAxB[i] = (decimal)(temp);
}
return Convert.ToDecimal(Result);
}
}
}
You need to add a Constructor in your class and in that constructor you can define the size for your property
public class Expected_and_Risk
{
//......//your code here
public Expected_and_Risk()
{
this.Prop = new decimal[10]; // this will define an array of 10 decimal elements for Prop
}
}
Also read about object oriented programming, Also check out this article An Intro to Constructors in C#
At the moment, you've got arrays within Expected_and_Risk, but you're never initializing the variables. You could do so within a constructor:
public Expected_and_Risk(int count)
{
Name = new string[count];
...
}
... but I'd suggest that's actually a nasty design. Any time you have lots of collections, all with the same count, where x[0] corresponds to y[0] and z[0] etc, you should consider having one collection of a custom type representing the encapsulation of those properties. For example:
// Must be an int, not a decimal - you can't create an array with a decimal count
int count = abc.Forecast.Count();
// Note: rename type to follow .NET naming conventions
Expected_and_Risk[] results = new Expected_and_Risk[count];
for (int i = 0; i < count; i++)
{
results[i].Name = abc[i].Name;
...
}
... except that of course now abc would be an array too. (It's not clear whether you're really just trying to copy all the values here, or whether you've got some business logic involved. There are better ways of copying values.)
Alternatively, if you really do want collections within Expected_and_Risk, you might want to consider using List<T> instead of arrays. That way you don't need to specify the count up-front.
Better way could be to add following method into Expected_and_Risk class and call it from within constructor.
EDIT - edit is done to make Initialize private, and call it within constructor.
void Initialize(int size)
{
Prop = new decimal[size];
AxB = new decimal[size];
Forecast = new decimal[size];
PowAxB = new decimal[size];
Name = new string[size];
}
public Expected_and_Risk(int size)
{
....
Initialize(size);
}
After that use it in ExpectValue like
Expected_and_Risk Result = new Expected_and_Risk(size)// size is 10 in example;

NullReference Exception when assigning to a Class Integer[]

I want to be able to transfer values from one DataGridView in Form1 to another DataGridView in Form3. To do this I've chosen to filter them in 3 different variables which would be in classes so that i could access them later in Form3.
These are the classes: (I've had them as a single one with 3 variables already)
public class verify1
{
public static int[] CodUser { get; set; }
}
public class verify2
{
public static DateTime[] DataFim{ get; set; }
}
public class verify3
{
public static string[] Nome { get; set; }
}
Altho, when i am assigning values to the variables i get a NullReferenceException right in the first time the for runs.
This is the code i used to assign values:
int a = 0;
for (int i = 0; i < dataGridView1.RowCount - 1; i++)
{
DateTime date = Convert.ToDateTime(dataGridView1.Rows[i].Cells[2].Value);
if (date <= DateTime.Now)
{
verify1.CodUser[a] = Convert.ToInt32(dataGridView1.Rows[i].Cells[0].FormattedValue);
verify2.DataFim[a] = Convert.ToDateTime(dataGridView1.Rows[i].Cells[2].FormattedValue);
verify3.Nome[a] = Convert.ToString(dataGridView1.Rows[i].Cells[3].Value);
a++;
}
}
Now, what i don't understand is why Visual Studio says the value is null. The exception happens in the following line:
verify1.CodUser[a] = Convert.ToInt32(dataGridView1.Rows[i].Cells[0].FormattedValue);
(which is 17389) in the first place and won't let me go further. I cant see why it's returning null. By the way, the DataGridView is fully fulfilled with data.
Why is it returning null?
You have the public properties defined in your verify1 class, but you never initialize them. They're null.
You need to initialize the arrays before you use them:
int a = 0;
int rowCount = dataGridView1.RowCount;
verify1.CodUser = new int[rowCount];
verify2.DataFim = new DateTime[rowCount];
verify3.Nome = new string[rowCount];
You might also want to take another look at how to use classes properly. I'm guessing you don't need three separate classes each with a single static property. It looks like you should have a single VerifyInfo class with three fields. You can then store those in a List<T>:
public class VerifyInfo
{
public int CodUser { get; set; }
public DateTime DataFim { get; set; }
public string Nome { get; set; }
}
And then your loop code would be much cleaner:
var verifyInfos = new List<VerifyInfo>();
for(int i = 0; i < dataGridView1.RowCount - 1; i++)
{
var date = Convert.ToDateTime(
dataGridView1.Rows[i].Cells[2].Value);
if(date <= DateTime.Now)
{
verifyInfos.Add(new VerifyInfo
{
CodUser = Convert.ToInt32(dataGridView1.Rows[i].Cells[2].Value),
DataFim = Convert.ToDateTime(
dataGridView1.Rows[i].Cells[2].FormattedValue),
Nome = Convert.ToString(dataGridView1.Rows[i].Cells[3].Value)
});
}
}
The auto-properties are automatically intialized to default value of the returning type.
You are dealing with reference type Array. The defalt value for the reference type is null.
It's better, in this case, avoid to have auto properties, but use ordinary ones.
Example:
public class verify1
{
static List<int> codUser = new List<int>(); //definition
public static List<int> CodUser
{
get { return codUser;}
set {codUser = value;}
}
}
I esplicitly used a List<T> in this case, cause in moment of declaration you don't know the excat size of array, and alsoo, according to the code provided, it can vary.
EDIT
Can use it like this (in practice like you did before)
for (int i = 0; i < dataGridView1.RowCount - 1; i++)
{
DateTime date = Convert.ToDateTime(dataGridView1.Rows[i].Cells[2].Value);
if (date <= DateTime.Now)
{
verify1.CodUser[a].Add( Convert.ToInt32(dataGridView1.Rows[i].Cells[0].FormattedValue));
......
....
}
}
Hope this helps.
Isn't verify1.CodUser null? How do you create it?
EDIT:
I've editted my answer to reply to Bruno's comment. You have to initialize your arrays first to be able to use them. To make a simple test, please create a separate project, paste these two lines, run your project in debug mode and set the breakpoint after array2 is created:
Int32[] array1;
Int32[] array2 = new Int32[3];
What do you see in the first array? It is null because it wasn't initialized. All you have to do is to initialize your arrays as I did with array2.
Hope this helps,
Piotr
*sorry for formatting, stackoverflow javascript is somehow blocked for me.

How can i add column name in list generic?

class MyExcelSheets
{
public List MyColumnNames { get; set; }
}
how can i add Excel data's column name in "List MyColumnNames ". it returns to me Object reference not set to an instance of an object.
i want to use above class in:
myexcelSheet = new MyExcelSheets();
myexcelSheet.MyColumnNames = new MyExcelSheets().MyColumnNames;
foreach (DataColumn col in dTable.Columns)
myexcelSheet.MyColumnNames.Add(col.ColumnName.ToString());
How can i solve it? Error: NullReferenceException
Assuming that public List MyColumnNames { get; set; } is actually declared as public List<string> MyColumnNames { get; set; }
The row:
myexcelSheet.MyColumnNames = new MyExcelSheets().MyColumnNames;
Should be:
myexcelSheet.MyColumnNames = new List<string>;
Though it would normally be better to do this in a constructor or something.
The Code myexcelSheet.MyColumnNames = new MyExcelSheets().MyColumnNames; only obtains the reference to the property , but it doesnt instantiate that.
Adding the code
this. MyColumnNames = new List<string>;
in a static constructor will solve the issue , as this part of the code will be called by the run time and we dont have to worry about instantiating state transfer objects (as it is in this case)
E.g.,
static MyExcelSheets(){this. MyColumnNames = new List<string>; }
Thanks,
Vijay

Categories