Null reference c# - 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.

Related

Can't search for the max value into an array

My problem is that i can't search into an array using linq in order to find an object property and set that as an id.
I need the method to search in the array for other model.idCliente and set that value as the "nextid + 1", in order to use it as id and the next array index.
Since the array's empty, the program adds the new object correctly, but when entering in the else if case, i get an axception for "a as null".
This is my code (where i get an exception on the else if linq line saying that "a" is null):
//Arrays
ClienteModel[] MemoryClienti = new ClienteModel[19];
OrdineModel[] MemoryOrdini = new OrdineModel[19];
//Aggiungi
public bool CreateCliente(ClienteModel model)
{
if (MemoryClienti[0] == null)
{
int defaultID = 0;
int defaultIndex = 0;
model.IDCliente = defaultID;
MemoryClienti[defaultIndex] = model;
}
else if (MemoryClienti[0]!=null)
{
var maxID = MemoryClienti.Max(a => a.IDCliente);
model.IDCliente = maxID++;
MemoryClienti[maxID++] = model;
}
return true;
}
This is the code of the form click:
//Aggiungi Cliente
private void aggiungiClienteButton_Click(object sender, EventArgs e)
{
clienteModel.Cognome = cognomeTextBox.Text;
clienteModel.Nome = nomeTextBox.Text;
clienteModel.Indirizzo = indirizzoTextbox.Text;
dbMemoryManager.CreateCliente(clienteModel);
MessageBox.Show("Cliente aggiunto correttamente.");
cognomeTextBox.Text = String.Empty;
nomeTextBox.Text = String.Empty;
indirizzoTextbox.Text = String.Empty;
}
This is the ClienteModel class:
public class ClienteModel
{
public int IDCliente { get; set; }
public string Cognome { get; set; }
public string Nome { get; set; }
public string Indirizzo { get; set; }
}
Wouldn't the following code achieve what you are trying to do?
ClienteModel[] MemoryClienti = new ClienteModel[19];
OrdineModel[] MemoryOrdini = new OrdineModel[19];
int maxID = 0; /* 0 is not a valid ID. IDs start from 1 */
//Aggiungi
public bool CreateCliente(ClienteModel model)
{
if(maxID <= MemoryClienti.Length) {
MemoryClienti[maxID++] = model; // copy the reference
model.IDCliente = maxID; // update the object's ID
return true;
} else {
return false; // can't add. array is full
}
}
If you are also doing deletions, you are better off using a List as others have also suggested.

How to initialise nested arrays

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"
}
}
}
};

Can't add Lazy initialized object to Generic List

I have generic list:
class BooksRegister <T>
{
private T[] Register;
public int Count { get; set; }
public BooksRegister()
{
Register = new T[100];
Count = 0;
}
public void Add(T value)
{
if (Count >= 100)
{
return;
}
Register[Count] = value;
Count ++;
}
}
then object class:
class Book
{
public String Author { get; set; }
public String Title { get; set; }
public int Quantity { get; set; }
public Book(String aut, String pav, int kiek)
{
this.Author = aut;
this.Title = pav;
this.Quantity = kiek;
}
public override string ToString()
{
return Author + " \"" + Title + "\" " + Quantity;
}
}
Then goes my Data class where I am reading information from file. I need to implement lazy initialization of object but when I do so I can't store my object in List.
public static void ReadBooks(BooksRegister<Book> allBooks)
{
StreamReader sr = new StreamReader("ListOfBooks.txt");
string line = "";
while ((line = sr.ReadLine()) != null)
{
string[] words = line.Split('|');
String tempAuthor = words[0];
String tempTitle = words[1];
int quant = Convert.ToInt32(words[2]);
Lazy<Book> tempas = new Lazy<Book>();
tempas.Value.Author = tempAuthor;
tempas.Value.Title = tempTitle;
tempas.Value.Quantity = quant;
allBooks.Add(tempas); // error here
}
How can I solve this problem? I have to use lazy initialization necessarily
If you must use lazy there are 2 ways:
You change you lazy initialization code with:
Lazy<Book> tempas = new Lazy<Book>(() => new Book(tempAuthor, tempTitle, quant));
allBooks.Add(tempas.Value);
What it does is defines an expression on how to initialize the book. This is a bad approach because you initialize lazy object on line one, and you initialize it on the second line, which basically makes using Lazy<Book> useless.
Another approach would be to change the method signature to
public static void ReadBooks(BooksRegister<Lazy<Book>> allBooks)
In this case your lazy initializing code would look like this:
Lazy<Book> tempas = new Lazy<Book>(() => new Book(tempAuthor, tempTitle, quant));
allBooks.Add(tempas);
One thing that is missing in this case is how to access Book in BooksRegister, as now it is write only object - you can add value, but there is no way to read it from outside the class.

Changing struct to class?

I want to change my struct Patient to a class but when I do my program don't work(free of errors) I want to substitute the struct patient for class patientn, as you can see my button click uses the struct patient and I want to change it for a class and still work.
visual studio 10 My program:
public partial class Form1 : Form
{
int itemCountInteger;
public struct Patient
{
public string patientidstring;
public string firstNameString;
public string lastNameString;
}
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
public class Patientn
{
private int patientId;
public string firstName;
private string lastName;
public Patientn()
{
patientId = 0;
firstName = "";
lastName = "";
}
public Patientn(int idValue, string firstNameVal, string lastNameVal)
{
patientId = idValue;
firstName = firstNameVal;
lastName = lastNameVal;
}
}
//Array
Patient[] patientInfo = new Patient[10];
//this method is used to add items to array and display listbox
private void button1_Click(object sender, EventArgs e)
{
try
{
foreach (Patient patientinfoIndex in patientInfo)
patientInfo[itemCountInteger].patientidstring = textBox1.Text;
patientInfo[itemCountInteger].firstNameString = textBox2.Text;
patientInfo[itemCountInteger].lastNameString = textBox3.Text;
string names = patientInfo[itemCountInteger].firstNameString + " " + patientInfo[itemCountInteger].lastNameString;
listBox1.Items.Add(names);
itemCountInteger++;
listBox1.SelectedItem = names;
}
catch
{
MessageBox.Show("Contacts are limited to 20. Please delete some contacts prior to adding more.");
}
}
You should explicitly create class instances. In your case
// It's quite enough since Patient is a struct
Patient[] patientInfo = new Patient[10];
In case of Patientn that is class it should be
// As it was...
Patientn[] patientInfo = new Patientn[10];
// You should add this since Patientn is a class
for (int i = 0; i < patientInfo.Length; ++i)
patientInfo[i] = new Patientn();

Displaying all items in another class

My problem is that I have a List<> variable connected to another class, and I want to get all the items from that List<> and put it into a string.
In the result string, i'd like to see callNum, copyNum, content, author, year, title
Here is where I'm trying to put it into a string
public class CItemControl
{
//declare a list variable
private List<CItem> mItems;
private CItem mNewItem;
//a method that instantiates the list
public CItemControl()
{
mItems = new List<CItem>();
}
//attribute to get all items
public List<CItem> Items
{
get { return mItems; }
}
public CItem NewItem
{
get { return mNewItem; }
}
//method to add item to the CItem list
public void AddItem(int callNum, int copyNum, string content, string author, string year)
{
mNewItem = new CItem(callNum, copyNum, content, author, year);
mItems.Add(mNewItem);
}
//method to return all items to a string
public CItem ListAllItems()
{
string allItems;
}
Here is the class where I'm trying to get the items from. There will be variables added later.
class CItem
{
//declare attributes
private string mTitle;
private string mAuthor;
private string mContent;
private string mYear;
private int mCopyNum;
private int mCallNum;
private bool mHold = false;
private bool mBorrowed = false;
private bool mShelf = false;
//overload a constructor
public CItem(int CallNum, int CopyNum, string Content, string Author, string Year)
{
callNum = CallNum;
copyNum = CopyNum;
content = Content;
author = Author;
year = Year;
}
//create the default constructor
public CItem()
{
callNum = 0;
copyNum = 0;
content = "";
author = "";
year = "";
}
//set attributes
public int callNum
{
get { return mCallNum; }
set { mCallNum = value; }
}
public string content
{
get { return mContent; }
set { mContent = value; }
}
public string author
{
get { return mAuthor; }
set { mAuthor = value; }
}
public string year
{
get { return mYear; }
set { mYear = value; }
}
public string title
{
get { return mTitle; }
set { mTitle = value; }
}
public int copyNum
{
get { return mCopyNum; }
set { mCopyNum = value; }
}
public bool hold
{
get { return mHold; }
}
public bool borrowed
{
get { return mBorrowed; }
}
public bool shelf
{
get { return mShelf; }
}
//display information for users
public string displayInfo()
{
return "Call Number: " + callNum + ". Copy Number: " + copyNum + ". Title: " + title +
". Author: " + author + ". Year Published: " + year + ". Content: " + content;
}
//new method to display status of item
public string displayStatus()
{
if (borrowed == true)
return "Item is currently being borrowed.";
if (shelf == true && hold == false)
return "Item is available for borrowing.";
else
return "Item is on hold";
}
Any help is much appreciated!
Thanks in advance.
ListAllItems shall look something like this
public string ListAllItems()
{
var sb = new StringBuilder(); // var is of type StringBuilder
mItems.ForEach(item => sb.Append(item.displayInfo());
return sb.ToString();
}
return String.Join("; ", allItems.Select(item => item.displayInfo()));
You don't provide a lot of informations on how and what informations you want in your result string.
Can't you achieve this objective with a simple loop ?
using System.Text;
(...)
public string ListAllItems()
{
StringBuilder allItems = new StringBuilder();
foreach(CItem itm in Items){
allItems.AppendLine(itm.displayInfo());
}
return allItems.ToString();
}
Stringbuilder is optional but is faster than string concatenation.
I don't normally like to add formatter methods to property bags like this. If you want the flexibility to change have many formatting implementations, you might want to make a seperate class do the formatting.
public interface IFormatter<in T>
{
string Format(T obj);
}
public class CItemFormatter : IFormatter<CItem>
{
public string Format(CItem item)
{
//formatting logic
}
}

Categories