How to initialise nested arrays - c#

Forgive a stupid question but I am new to C# & OOP.
Can anyone help me prevent a “System.NullReferenceException:”?
I’m trying to do an assignment following instructions and using what we’ve learned to date (arrays, classes and constructors).
I’ve created an array of StudentSubjects classes and embedded this in an array of Student classes.
I want to print out details of each student’s subjects.
I can access the StudentArray[0] fields OK but can’t get to the StudentArray[0].StudentSubjectsArray[0] fields because "Object reference not set to an instance of an object”
I’ve spent 2 weeks looking for an answer but cannot find any examples of how to set
StudentArray[0].StudentSubjectsArray[0].SubjectName = "Algebra";
Any advice most appreciated. My code is below ....
using System;
namespace Nested_Arrays
{
public class Program
{
static void Main(string[] args)
{
Student[] StudentArray = new Student[1];
Console.WriteLine($"Hello");
StudentArray[0] = new Student();
StudentArray[0].StudentName = "Peter";
StudentArray[0].StudentLocation = "Australia";
Console.WriteLine($"{StudentArray[0].StudentName,10} {StudentArray[0].StudentLocation,15}");
StudentArray[0].StudentSubjectsArray[0].SubjectName = "Algebra";
StudentArray[0].StudentSubjectsArray[0].StudentsResult = "Pass";
Console.WriteLine($"{StudentArray[0].StudentName,10} {StudentArray[0].StudentLocation,15} {StudentArray[0].StudentSubjectsArray[0].SubjectName,15} {StudentArray[0].StudentSubjectsArray[0].StudentsResult,10}");
Console.WriteLine($"Goodbye");
}
public class Student
{
public string StudentName;
private string studentName
{ get { return studentName; } set { studentName = value; } }
public string StudentLocation;
private string studentLocation
{ get { return studentLocation; } set { studentLocation = value; } }
public StudentSubjects[] StudentSubjectsArray;
private StudentSubjects[] studentSubjectsArray
{ get { return studentSubjectsArray; } set { studentSubjectsArray = value; } }
//Constructor
public Student() { }
}
public class StudentSubjects
{
public string SubjectName;
private string subjectName
{ get { return subjectName; } set { subjectName = value; } }
public string StudentsResult;
private string studentsResult
{ get { return studentsResult; } set { studentsResult = value; } }
//Constructor
public StudentSubjects() { }
}
}
}

You just need to add the following:
StudentArray[0].StudentSubjectsArray = new StudentSubjects[1];
StudentArray[0].StudentSubjectsArray[0] = new StudentSubjects();
// and only then
StudentArray[0].StudentSubjectsArray[0].SubjectName = "Algebra";

In my opinion, a good practice is to initialize arrays in the constructor. In this way you are sure it is not null when using the object.
So do something like:
//Constructor
public Student() {
this.studentSubjectsArray = new StudentSubjects[1];
}

As others have said, you need to create the arrays before you assign objects in the array, although you can do both at the same time.
For example, if you want to do it all in one line, this would work:
Student[] StudentArray = {
new Student {
StudentName = "Peter",
StudentLocation = "Australia",
StudentSubjectsArray = new[] {
new StudentSubjects {
SubjectName = "Algebra",
StudentsResult = "Pass"
}
}
}
};

Related

Singleton property not updating during "OnClicked" event

I'm sure I remember this being a threading issue, but I can't find an answer. It seems like it should be simple. I have the following code:
private void Dingle_Clicked(object sender, RoutedEventArgs e)
{
dynamic doc = ScraperBrowser.Document;
string htmlText = doc.documentElement.InnerHtml;
htmlText = htmlText.Replace("\r\n", " ");
Regex targetStart = new Regex(this works just fine);
MatchCollection target = targetStart.Matches(htmlText);
string priceData = target[0].Value;
foreach (StorePriceData spData in Lists.Singleton.MedicineList[medIndex].Prices)
{
Regex rx = new Regex(spData.StoreName + #".+?(\$\d+\.\d+)");
MatchCollection matches = rx.Matches(priceData);
if (matches.Count > 0)
{
if (matches[0].Groups.Count > 0)
{
spData.MedicinePrice = matches[0].Groups[1].Value;
}
}
}
string cookie = Application.GetCookie(new Uri("https://www.goodrx.com"));
++medIndex;
ScraperBrowser.Navigate(Lists.Singleton.MedicineList[medIndex].GoodRxUrlString);
}
The problem I'm having is that the spData.MedicinePrice takes the value, but the value in the singleton "MedicineList" is not being updated. How can I make that value update?
The singleton code:
public class Lists
{
private static Lists _singleton;
public static Lists Singleton
{
get
{
if (_singleton == null) _singleton = new Lists(); return _singleton;
}
}
public List<MedicineInfo> MedicineList {
get
{
return new List<MedicineInfo>()
{
new MedicineInfo() { Name = "ZOLPIDEM TAB 10MG", Doses = "30 tablets" },
new MedicineInfo() { Name = "PANTOPRAZOLE TAB 40MG", Doses = "30 tablets" }
};
}
}
}
MedicineInfo class code:
public class MedicineInfo
{
public MedicineInfo()
{
Prices = new List<StorePriceData>()
{
new StorePriceData() { StoreName = "xxxx" },
new StorePriceData() { StoreName = "yyyy" },
new StorePriceData() { StoreName = "zzzz" },
};
}
public string Name { get; set; }
public string Doses { get; set; }
public List<StorePriceData> Prices { get; set; }
}
Thanks!
Carl
You are returning a new List<MedicineInfo> each time the getter of MedicineList is called.
Also, Lists is not really a singleton. A better implementation would look something like this:
public sealed class Lists
{
private static readonly Lists _singleton = new Lists();
private readonly List<MedicineInfo> _medicineList = new List<MedicineInfo>
{
new MedicineInfo() { Name = "ZOLPIDEM TAB 10MG", Doses = "30 tablets" },
new MedicineInfo() { Name = "PANTOPRAZOLE TAB 40MG", Doses = "30 tablets" }
};
private Lists() { }
public static Lists Singleton => _singleton;
public List<MedicineInfo> MedicineList => _medicineList;
}

Null reference c#

Im writing a code where you can search a name and the subjects teaches will pop-up etc..
however I'm not really sure why but i'm getting Object reference not set to an instance of an object error im missing something i know, can someone help me? i tried different methods didn't really work... heres my code :
public partial class MainWindow : Window
{
Course my = new Course();
public class Course
{
public string[] Name { get; set; }
public string[] Subject { get; set; }
public string[] Hour { get; set; }
public Course(string[] name, string[] subject, string[] hour)
{
this.Name = name;
this.Subject = subject;
this.Hour = hour;
}
}
public MainWindow()
{
InitializeComponent();
my.Name[0] = "Ali";
my.Name[1] = "Sefer";
my.Subject[0] = "INFORMATIKA";
my.Subject[1] = "ENGLISH";
my.Hour[0] = "12";
my.Hour[1] = "22";
}
private void searchButton_Click(object sender, RoutedEventArgs e)
{
Find();
}
private void Find()
{
int index = 0;
string wanted = wantedName.Text;
while (my.Name[index] != wanted && (my.Name[index] != "END"))
{
index++;
}
if (my.Name[index] == wanted)
{
outputLabel.Content = " " + my.Name[index] + " " + my.Subject[index];
}
else
{
outputLabel.Content = "Name not found";
}
}
}
}
You are using arrays without initializing them. While you have defined a constructor for your Course class that takes values for the arrays, you are using the default constructor. Try calling your own constructor with arguments like
Course my = new Course(new string[2], new string[2], new string[2]);
Before you can assign a value to an element like my.Name[0], you have to ensure that my.Name is referencing an allocated array, which means there is memory available for your elements.

C# Array Syntax when using object oriented programming [duplicate]

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 6 years ago.
I have the following partial classes:
public partial class FormInstance
{
private string referenceField;
public string Reference
{
get { return this.referenceField; }
set { this.referenceField = value; }
}
}
public partial class FormField
{
private string fieldNameField;
private string fieldValueField;
public string FieldName
{
get { return this.fieldNameField; }
set { this.fieldNameField = value; }
}
public string FieldValue
{
get { return this.fieldValueField; }
set { this.fieldValueField = value; }
}
}
public partial class EFormData
{
private FormInstance formInstanceField;
private FormField[] formDataField;
public FormInstance EFormInstance
{
get { return this.formInstanceField; }
set { this.formInstanceField = value; }
}
public FormField[] FormData
{
get { return this.eformDataField; }
set { this.eformDataField = value; }
}
}
I have a method as follows which has a parameter that is of the above class object type:
public int writeEformData(EformData formFields)
{
object[] results = this.Invoke("writeEformData", new object[] {
formFields});
return ((int)(results[0]));
}
In my code I'm trying to initialise the EformData object as follows:
EformData eformData = new EformData ();
eformData.EformInstance.Reference = "1234";
eformData.FormData[0].FieldName = "txt_name";
eformData.FormData[0].FieldValue = "John Doe";
eformData.FormData[1].FieldName = "txt_address";
eformData.FormData[1].FieldValue = "10 Acacia Ave";
int result = web.writeEformData(eformData);
but when I debug I get error on line 2 eformData.EformInstance.Reference = "1234";
An unhandled exception of type 'System.NullReferenceException' occurred
Additional information: Object reference not set to an instance of an object.
Whats the correct syntax to initialise the EformData object and assigning values as I'm trying to do above?
replace
eformData.EformInstance.Reference = "1234";
with
eformData.EFormInstance = new FormInstance() { Reference = "1234" };
..and you will have the same troulbe in the following lines. You have to create a instance of each object before you can set a value to its properties
eformData.FormData = new FormField[2];
eformData.FormData[0] = new FormField() { FieldName = "txt_name", FieldValue = "John Doe" };

Adding values using LINQ to an object property with a Dictionary property

I have a dataset which returns a couple of contact information in string(Phone, mobile, skype). I created an object with a Dictionary property where i can put the contact information in a key value pair. The problem is, I am assigning the values of the object using Linq. Hope somebody can help. Here is my code:
public class Student
{
public Student()
{
MotherContacts = new ContactDetail();
FatherContacts = new ContactDetail();
}
public ContactDetail MotherContacts { get; set; }
public ContactDetail FatherContacts { get; set; }
}
public class ContactDetail
{
public ContactDetail()
{
Items = new Dictionary<ContactDetailType, string>();
}
public IDictionary<ContactDetailType, string> Items { get; set; }
public void Add(ContactDetailType type, string value)
{
if(!string.IsNullOrEmpty(value))
{
Items.Add(type, value);
}
}
}
public enum ContactDetailType
{
PHONE,
MOBILE
}
Here's how I assign value to the Student object:
var result = ds.Tables[0].AsEnumerable();
var insuranceCard = result.Select(row => new Student()
{
MotherContacts.Items.Add(ContactDetailType.PHONE, row.Field<string>("MotherPhone"),
MotherContacts.Items.Add(ContactDetailType.MOBILE, row.Field<string>("MotherMobile")
}).FirstOrDefault();
The compiler says that the MotherContacts is not recognized in the context. What should I do?
I think your code should look like:
var insuranceCard = result.Select(row =>
{
var s = new Student();
s.MotherContacts.Items.Add(ContactDetailType.PHONE, row.Field<string>("MotherPhone");
s.MotherContacts.Items.Add(ContactDetailType.MOBILE, row.Field<string>("MotherMobile");
return s;
}).FirstOrDefault();
You are using the object initializer syntax in a wrong way. The correct use is:
new Student{MotherContacts = value} where value must be a ContactDetail.

Adding a list to a dictionary

In my program I have a list of marks and a dictionary which stores the studentId. I want that the user enters the studentId and according to that id it will point to the list of marks. I think I am implementing it incorrectly. Can someone help me in implementing it. Thanks
public class Student() {
private string name;
private string surname;
private string dob;
private string address;
private int id;
public Student()
{
}
public Student(string year,string name, string surname, string dob, string address)
{
this.name = name;
this.surname = surname;
this.dob = dob;
this.address = address;
this.year = year;
}
public string Name
{
get { return name; }
set { name = value; }
}
public string Surname
{
get { return surname; }
set { surname = value; }
}
public string DOB
{
get { return dob; }
set { dob = value; }
}
public string Addr
{
get { return address; }
set { address = value; }
}
public int Id
{
get { return id; }
set { id = value; }
}
private string year;
public string Year
{
get { return year; }
set { year = value; }
}
public Student(string s)
{
string[] splitted = s.Split(',');
name = splitted[0];
surname = splitted[1];
dob = splitted[2];
address = splitted[3];
// id = splitted[4];
}
public Dictionary<int,List<Marks>> dictionary= new Dictionary<int,List<Marks>>();
public List<Marks> Mathematics = new List<Marks>();
public List<Marks> English = new List<Marks>();
public List<Marks> Maltese = new List<Marks>();
public List<Marks> ReligiousStudies = new List<Marks>();
public List<Marks> SocialStudies = new List<Marks>();
public Dictionary<int, List<Marks>> dictionar = new Dictionary<int, List<Marks>>();
public void AddMarks(int hyexam, int anexam)
{
{
Console.WriteLine("enter id of student to input marks to:");
string id = Console.ReadLine();
if (dictionar.ContainsKey(Id).Equals(id))
{
Mathematics.Add(new Marks(hyexam, anexam));
English.Add(new Marks(hyexam, anexam));
Maltese.Add(new Marks(hyexam, anexam));
ReligiousStudies.Add(new Marks(hyexam, anexam));
SocialStudies.Add(new Marks(hyexam, anexam));
dictionar.Add(id, (Mathematics)); //dont know how to implement it
}
else
{
Console.WriteLine("id not found");
}
}
}
public class Marks
{
private int hyexam;
private int anexam;
private string id;
public int HYEXAM
{
get { return hyexam; }
set { hyexam = value; }
}
public int ANEXAM
{
get { return anexam; }
set { anexam = value; }
}
public string Id
{
get { return id; }
set { id = value; }
}
public Marks(int hyexam, int anexam)
{
this.hyexam = hyexam;
this.anexam = anexam;
}
public Marks(string id)
{
this.id = id;
}
public double OverallExam()
{
return (0.4 * hyexam) + (0.6 * anexam);
}
}
}
I'd say the main problem is your modelling. You've included the Dictionary<int, List<Marks>> as a field within Student. That means that each Student object has a dictionary. That makes no sense - because the key for the dictionary is meant to be the student ID, right?
It probably makes sense for each Student object to the lists of marks as you've currently got (although not as public fields, IMO). Given that information, do you really need a Dictionary going to the marks at all? Wouldn't it be cleaner to have a Dictionary<int, Student> somewhere (not in the Student class - maybe in a School class?) mapping each student ID to a Student, and you can get the marks from the Student?
Think hard about what you're trying to achieve, and where the data really belongs. In my experience, when you've got the data modelling right, the code usually follows in a clean way.
(I'd also question your Marks class, both in terms of name and design. What are those properties meant to represent? Isn't it really a single mark in an exam? Perhaps ExamResult would be clearer? Does it really need to be mutable?)
I'd agree with Jon that this is definitely a modeling issue (based on the OP's other posts). If you're new to object oriented programming, the first thing you need to do is determine what objects you'll need to create to answer the problem.
What is a Student? A student has a name, id, dob, class year, etc. For every attribute a student has, you need to set up a field or property.
public class Student
{
public int ID { get; set; }
public string Name { get; set; }
public DateTime DoB { get; set; }
... etc ...
}
What is a Mark? From your descriptions, a Mark has a subject, a mid-exam score, and an annual-exam score.
public class Mark
{
public string Subject { get; set; }
public int MidScore { get; set; }
public int FinalScore { get; set; }
}
What is the relationship between a Student and a Mark? A student has a list of marks associated with them. This is best described with a List<> object.
public class Student() // continued
{
public List<Mark> Marks { get; set; }
}
Once you have the basics set up for your objects, it will be easier to filter out what you DON'T need, and make it much easier to answer your question. :)
My proposal:
Your "Mark" class must have something that identifies the subject (could be an enum called Subject, or an string, or an int with the ID of the subject if you have it stored in database)
Then you could have:
Console.WriteLine("enter id of student to input marks to:");
string id = Console.ReadLine();
var marks = new Dictionary<int, List<Mark>>();
if (UserExists(id))
{
Console.WriteLine("mark for subject1:");
string s1 = Console.ReadLine();
Console.WriteLine("mark for subject2:");
string s2 = Console.ReadLine();
var list = new List<Mark>();
list.Add(new Mark { Subject = SubjectEnum.Subject1, Value = Convert.ToDecimal(s1), });
list.Add(new Mark { Subject = SubjectEnum.Subject2, Value = Convert.ToDecimal(s2), });
marks.Add(Convert.ToInt32(id), list)
}
else
{
Console.WriteLine("id not found");
}
Hope this helps.

Categories