Null Reference Exception was unhandled C# console application - c#

I know this is probably similar to some other posts, but I'm not quite sure what I'm doing wrong here. As an FYI, I'm new to programming and still trying to learn proper flow.
Here is the code, the exception occurs at "MyFriends[i].Name = friendName".
using System;
using System.Collections;
namespace FriendList
{
class FriendList
{
static public Friend[] MyFriends = new Friend[2];
public static void Main()
{
string friendName;
string friendPhone, friendMonth, friendDay, friendYear;
int intMonth, intDay, intYear;
for (int i = 0; i < 2; ++i)
{
Console.Write("enter name");
friendName = Console.ReadLine();
MyFriends[i].Name = friendName;
Console.Write("phone");
friendPhone = Console.ReadLine();
MyFriends[i].Phone = friendPhone;
Console.WriteLine("Enter Month: ");
friendMonth = Console.ReadLine();
intMonth = Convert.ToInt32(friendMonth);
MyFriends[i].Month = intMonth;
Console.WriteLine("Enter Day: ");
friendDay = Console.ReadLine();
intDay = Convert.ToInt32(friendDay);
MyFriends[i].Day = intDay;
Console.WriteLine("Entery Year: ");
friendYear = Console.ReadLine();
intYear = Convert.ToInt32(friendYear);
MyFriends[i].Year = intYear;
}
for (int i = 0; i < 2; ++i)
{
string information = string.Format("first name: {0}, phone {1}", MyFriends[i].Name, MyFriends[i].Phone);
Console.WriteLine(information);
}
Console.Read();
}
}
class Friend
{
string _Name = string.Empty, _Phone = string.Empty;
int _Day = 0, _Month = 0, _Year = 0;
public string Name
{
get { return _Name; }
set { _Name = value; }
}
public string Phone
{
get { return _Phone; }
set { _Phone = value; }
}
public int Month
{
get { return _Month; }
set { _Month = value; }
}
public int Day
{
get{ return _Day; }
set{ _Day = value ; }
}
public int Year
{
get { return _Year;}
set { _Year = value; }
}
public Friend()
{ }
}
}
Thank you for your guidance!

Your friend array is initialized empty. So MyFriends[i] will hit a null reference, which is another way to say you are trying to access something that doesn't exist.
In other words, you have an Array with slots for two friends, but both slots are empty. You still need to have a friend in each slot before you can use their properties, such as Name, Phone etc.
Simply start the for loop like this:
for (int i = 0; i < 2; ++i)
{
MyFriend[i] = new Friend(); //or pass parameters as required by the constructor
// rest of your code goes here
}
And things will be fine. This way, you are adding a friend to the slot you will be using.

You've created an array with two elements, but you have set the elements to any value. They are both null:
static public Friend[] MyFriends = new Friend[2];
So, when you try to use MyFriends[i] from the array, you're actually getting null.
MyFriends[i].Name = friendName;
That where your NullReferenceException came from.
You'll have to initialize the members of the array. For example:
for (int i = 0; i < MyFriends.Length; i++)
{
// Put a new Friend object in the array.
MyFriends[i] = new Friend();
// ...

When creating collections, they're populated with default values of the target type, and the default value for any reference type if null. So to solve your problem you'd have to initialize items in the array before accessing them:
....
for (int i = 0; i < 2; ++i)
{
MyFriends[i] = new Friend();
...

MyFriends is an array of Friend class.
each element in the array needs to be initialized with a friend constructor so it will be allocated with a memory.

Related

Linked List/Node Clas - Adding User Input to Linked List

I have the user inputting a string which is stored in the variable 'word'. I now want to add this stored variable to the linked list. I've tried using
LinkedList<string>.Add(word);
To add the variable to the linked this but it isn't working and is returning the error "An object reference is required for the non-static field, method or property 'LinkedList.Add(string)"
I'm assuming it has something to do with my linked list but I'm not to sure.
Any help or ideas on the issue would be great.
using System;
using System.Collections.Generic;
using System.Text;
namespace project
{
public class LinkedList<TData>
{
private Node<TData> head;
private int count;
public LinkedList(string word)
{
this.head = null;
this.count = 0;
}
public bool Empty
{
get { return this.count == 0; }
}
public int Count
{
get { return this.count; }
}
public TData this[int index]
{
get { return this.Get(index); }
}
public TData Add(int index, TData data)
{
if (index < 0)
throw new ArgumentOutOfRangeException("Index: " + index);
if (index > count)
index = count;
Node<TData> current = this.head;
if (this.Empty || index == 0)
{
this.head = new Node<TData>(data, this.head);
}
else
{
for (int i = 0; i < index - 1; i++)
{
current = current.Next;
current.Next = new Node<TData>(data, current.Next);
}
}
count++;
return data;
}
public TData Add(TData data)
{
return this.Add(count, data);
}
public TData Remove(int index)
{
if (index < 0)
throw new ArgumentOutOfRangeException("Index: " + index);
if (this.Empty)
return default(TData);
if (index >= this.count)
index = count - 1;
Node<TData> current = this.head;
TData result;
if (index == 0)
{
result = current.Data;
this.head = current.Next;
}
else
{
for (int i = 0; index < index - 1; i++) ;
current = current.Next;
result = current.Next.Data;
current.Next = current.Next.Next;
}
count--;
return result;
}
public void Clear()
{
this.head = null;
this.count = 0;
}
public int IndexOf(TData data)
{
Node<TData> current = this.head;
for (int i = 0; i < this.count; i++)
{
if (current.Data.Equals(data))
return i;
current = current.Next;
}
return -1;
}
public bool Contains(TData data)
{
return this.IndexOf(data) >= 0;
}
public TData Get(int index)
{
if (index < 0)
throw new ArgumentOutOfRangeException("Index: " + index);
if (this.Empty)
return default(TData);
if (index >= this.count)
index = this.count - 1;
Node<TData> current = this.head;
for (int i = 0; i < index; i++)
current = current.Next;
return current.Data;
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
namespace project
{
public class Node<TData>
{
private Node<TData> next { get; set; }
public Node(TData data, Node<TData> next)
{
this.Data = data;
this.next = next;
}
public TData Data { get; set; }
public Node<TData> Next
{
get { return this.next; }
set { this.next = value; }
}
}
}
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace project
{
class Program
{
static void Main(string[] args)
{
string word;
Console.WriteLine("Please enter a word");
word = Console.ReadLine();
Console.WriteLine("You typed: " + word);
Console.ReadKey();
var list = new LinkedList<string>(word);
LinkedList<string>.Add(word);
}
}
}
Change this:
var list = new LinkedList<string>(word);
LinkedList<string>.Add(word);
To this:
var list = new LinkedList<string>();
list.Add(word);
list is your linked list object in memory. Whenever you want to do something with your list, you use the variable reference list, not the name for the kind of object it is. The reason we use the name of the variable rather than the name of the kind is because we might very well want to have two or more of them in our program:
var postiveList = new LinkedList<string>();
var negativeList = new LinkedList<string>();
positiveList.Add("happy");
negativeList.Add("sad");
It's only possible to use the name of the type(kind), when you're using something declared as static - and nothing in your program is static that I can point to and make a suitable demonstration of. Something you'll have probably used though:
int x = Convert.ToInt32("1234");
Convert here is static, the name of a type of class. You don't need to make a new Convert before you use it, and you can't have (nor need) more than one Convert in a program, so it makes sense to have it be static (only one of them)
Some things are both static and not:
var startTime = new DateTime(1970,1,1);
var endTime = DateTime.UtcNow;
startTime and endTime are both instances of a DateTime. To get the end time, however, we used a static property UtcNow of the DateTime type. It created a new DateTime for us based on the value of the computer clock and returned it. We didn't need for any other datetime to exist before we did this. If it helps, think of these static things as being like factories that churn out manufactured objects on demand. There is only one factory, and the things it makes are always the same kind of thing but it can make millions of them
Also change this:
public LinkedList(string word)
{
this.head = null;
this.count = 0;
}
To this:
public LinkedList()
{
this.head = null;
this.count = 0;
}
There's no point asking for something and then not doing anything with it - it just makes the thing that asks harder to use. I get the feeling you didn't write LinkedList, but you might have added this in while trying to get a word into it
you write:
LinkedList<string>.Add(word);
This is an attempt to call a static method Add on the type LinkedList<string>. And the compiler is telling you that this is a instance method and not a static method. I.e. you want to call:
list.Add(word);
Also, the constructor
public LinkedList(string word)
takes a string, but does not do anything with it. This parameter should probably be removed.

How to assign a value to a field in different class?

In this program, I have 2 classes Application and Customer. I want to initialize Standard Fare with some value which should be entered by the user. Standard Fare field is in Customer class.
I did this, but it is not showing the desired result. When Calculate function is called The Value of Standard fare is becoming zero.
When I initialize the value of STANDARD_FARE in Customer class itself, then the program is working as desired.
How can I input the value given by the user to STANDARD_FARE?
Also methods like GetAge(), GetPassNo() in Application class is not returning the value of the same.
class Application
{
private static int Nop ;
private static double TotalFare=0;
Customer cust= new Customer();
static void Main(string[] args)
{
Application obj = new Application();
Console.Write("Enter the STANDARD RATE of the tour ");
obj.cust.StandardFare = int.Parse(Console.ReadLine());
a:
Console.Clear();
Console.WriteLine("Enter the number of passengers");
Nop = int.Parse(Console.ReadLine());
Application[] app = new Application[Nop];
if (Nop <= 0)
{
Console.WriteLine("Please enter a valid number of passengers");
Console.ReadKey();
goto a;
}
for (int i = 0; i < Nop; i++)
{
app[i] = new Application();
app[i].GetInformationFromCust();
}
for (int j = 0; j < Nop; j++)
{
app[j].cust.Display();
}
}
public int GetInformationFromCust()
{
b:
Console.Clear();
int slen = 0;
Console.WriteLine("Enter the title of the passenger");
cust.Customer_Title = Console.ReadLine();
Console.WriteLine("\r\nEnter passenger's First name :");
cust.Customer_FName = Console.ReadLine();
Console.WriteLine("\r\nEnter passenger's Last name :");
cust.Customer_LName = Console.ReadLine();
slen = cust.Customer_FName.Length + cust.Customer_LName.Length;
if (slen < 5 || slen > 15)
{
Console.WriteLine("\r\nName should be between 5 to 15 characters, Please try again ");
Console.ReadLine();
goto b;
}
c:
long x = 0, len = 0;
Console.WriteLine("\r\nEnter the passport number of the passenger ");
cust.CustomerPassNo = int.Parse(Console.ReadLine());
x = cust.CustomerPassNo;
while (x > 0)
{
x = x / 10;
++len;
}
if (len != 8)
{
Console.WriteLine("\r\nInvalid passport number, passport should be of 8 digits ");
goto c;
}
d:
Console.WriteLine("\r\nEnter the age of the passenger :");
cust.Customer_Age = int.Parse(Console.ReadLine());
if (cust.Customer_Age < 0)
{
Console.WriteLine("\r\nInvalid age, please enter a valid age ");
goto d;
}
cust.CalculatePrice();
return 0;
}
public int GetAge()
{
return cust.Customer_Age;
}
public double GetAirFare()
{
return cust.CustomerTicket ;
}
public long GetPassportNo()
{
return cust.CustomerPassNo;
}
public string GetTitle()
{
return cust.Customer_Title;
}
}
class Customer
{
const double K_DISCOUNT = 0.10;
const double S_DISCOUNT = 0.20;
private double STANDARD_FARE;
private string CustomerName { get; set; }
private int CustomerAge;
private string CustomerFName;
private string CustomerLName;
private long CustomerPassport;
private double CustomerPrice;
private string CustomerTitle;
private double KidDiscount;
private double SeniorDiscount;
public Customer()
{
this.KidDiscount = K_DISCOUNT;
this.SeniorDiscount = S_DISCOUNT;
}
public double StandardFare
{
get { return STANDARD_FARE; }
set { STANDARD_FARE = value; }
}
public int Customer_Age
{
get { return CustomerAge; }
set { CustomerAge = value; }
}
public string Customer_Title
{
get { return CustomerTitle; }
set { CustomerTitle = value; }
}
public string Customer_FName
{
get { return CustomerFName; }
set { CustomerFName = value; }
}
public string Customer_LName
{
get { return CustomerLName; }
set { CustomerLName = value; }
}
public long CustomerPassNo
{
get { return CustomerPassport; }
set { CustomerPassport = value; }
}
public double CustomerTicket
{
get { return CustomerPrice; }
set { CustomerPrice = value; }
}
public int CalculatePrice()
{
if (CustomerAge < 3)
{
CustomerPrice = 0;
}
else if (CustomerAge >= 3 && CustomerAge < 18)
{
CustomerPrice = STANDARD_FARE - (STANDARD_FARE * KidDiscount);
}
else if (CustomerAge > 65)
{
CustomerPrice = STANDARD_FARE - (STANDARD_FARE * SeniorDiscount);
}
else
{
CustomerPrice = STANDARD_FARE;
}
return 0;
}
public void Display()
{
//some code here
}
}
You are populating your array app with instances of Application that still have the default STANDARD_FARE value (which is 0.0), because you have never set it on those instances. You only set it on the obj.cust instance, which you never again use. Because STANDARD_FARE is an instance variable, changes to it have no affect on other (or future) instances.
You have the same problem in reverse with all the Application.Get* functions; they are getting properties of an object (obj.cust) that has never had any properties set, other than StandardFare/STANDARD_FARE.
The most obvious fix is to do away with obj and obj.cust entirely - they have no use other than to be confusing - and make STANDARD_FARE a static variable (and its setter StandardFare a static property).
BTW, your naming conventions are terrible and inconsistent; if I were your grader I'd dock you points for using unclear variable names(app, nop), and for using ALL_CAPS for non-constants (STANDARD_FARE). I'd also object to using a private auto-backed property (CustomerName, which is also never used) instead of simply a private variable, for not using auto-backed properties elsewhere (StandardFare as an explicitly-coded public getter and setter for STANDARD_FARE, etc.), and for copying constant values into non-settable instance variables (K_DISCOUNT to KidDiscount; just use the constant directly, or at least make KidDiscount static and add some non-private access to it). As others have mentioned, you of course should not be using goto in place of loops. I'll also mention the error-prone and inefficient checking the length of the passport number by repeated division instead of simply checking whether it's less than 99999999 (in theory, passport numbers might start with a zero, which would look like less than 8 digits after parsing, but you could also make sure it's greater than 10000000 if you want).

encapsulation of an array of objects c#

I would like to create an array of objects. Each object has it's own int array.
For each object I assign values to it's array ONLY with keys given by myself (example: li[i].V[10] = 1; li[i].V[50] = 10; )
Can someone tell me how to do that? Can I do that without using Lists?
The second case is analogical to first. I would like to know how to assign values of object's List
using setter.
I tried to do that by myself. Unfortunately My code crashed cuz I don't know how to set the dimension of V and Word:
class CFiles
{
//private int[] v=new int[5];//dont want to specify the dimention of array here
private int[] v;//vector of file
private List<string> words;
public CFiles()
{
words = Words;
v = new int[50];
v = V;
}
public int[] V { get; set; }
public List<string> Words { get; set; }
}
class Program
{
static void Main(string[] args)
{
CFiles[] li = new CFiles[2];
for(int i=0;i<li.Length;i++)
{
li[i]=new CFiles();
li[i].V[10] = 1;
li[i].V[50] = 10;
li[i].V[50] = 15;
li[i].Words.Add("a");
li[i].Words.Add("ab");
li[i].Words.Add("abc");
}
for (int i = 0; i < li.Length; i++)
{
for(int j=0;j<li[i].V.Length;j++)
{
Console.WriteLine(li[i].V[j]);
}
}
Console.WriteLine();
}
}
Your constructor isn't right and your properties aren't quite right. You might want something more like this:
class CFiles
{
//private int[] v=new int[5];//dont want to specify the dimention of array here
private int[] v;
public int[] V { get { return v; } set { v = value; } }
private List<string> words;
public List<string> Words { get { return words; } set { words = value; } }
public CFiles()
{
words = new List<string>();
v = new int[51]; //needs to be 51 if you are going to assign to index 50 below
}
}
Other than those issues, your code seems to do what you want. You have an array of objects where each object has its own int array (in addition to a string of strings).
Is that not what you want?

Populate ObjectListView using a List

I'm trying to populate a DataTreeListView from ObjectListView library using a list. Unfortunately I am unable to achieve it, there is nothing displayed even though there is a count of item inside the List itself.
Class.cs
public class Class
{
protected string xName;
protected int xId;
protected int xParentId;
protected int happinessStatus;
protected int salaryStatus;
public Class()
{
this.xName = "";
this.xId = 0;
this.xParentId = 0;
this.happinessStatus = 0;
this.salaryStatus = 0;
}
public String Name
{
get { return this.xName; }
set { this.xName = value; }
}
public int Id
{
get { return this.xId; }
set { this.xId = value; }
}
public int ParentId
{
get { return this.xParentId; }
set { this.xParentId = value; }
}
public int HappinessStatus
{
get {return this.happinessStatus; }
set { this.happinessStatus = value; }
}
public int SalaryStatus
{
get { return this.salaryStatus; }
set { this.salaryStatus = value; }
}
public static List<Class> GetList()
{
List<Class> oList = new List<Class>();
Class oClass = new Class();
oClass.Name = "Person A";
oClass.Id = 1;
oClass.ParentId = 0;
oClass.HappinessStatus = 1;
oClass.SalaryStatus = 1000;
oList.Add(oClass);
oClass.Name = "Person B";
oClass.Id = 2;
oClass.ParentId = 1;
oClass.HappinessStatus = 1;
oClass.SalaryStatus = 2000;
oList.Add(oClass);
oClass.Name = "Person C";
oClass.Id = 3;
oClass.ParentId = 1;
oClass.HappinessStatus = 1;
oClass.SalaryStatus = 1000;
oList.Add(oClass);
return oList;
}
On the MainForm's Load Event,
I did the following:
List<Class> list = new List<Class>();
list = Class.GetList();
dataTreeListView1.DataSource = list;
On the designer view, I've also created columns which has got aspect name set to each of the property of the class file except the Id and ParentId.
KeyAspectName : Id
ParentKeyAspectName: ParentId
I did a small messagebox to show the count of the item in the list, its correct but nothing displayed out on the dataTreeListView control.
May I know what is wrong with my coding?
Did you set KeyAspectName, ParentKeyAspectName and RootKeyValue accordingly?
If you did it using the designer, RootKeyValue may be your problem:
Due to the limitations of the Designer in the IDE, RootKeyValue can only be given a string value through the IDE. If your ParentKey is not of type string, you will have to set its value through code.
Since you parent key is of type int use
dataTreeListView1.RootKeyValue = 0;
Note that in contrast to the basic OLV, you don't need to add columns manually. If you want to hide the key columns set ShowKeyColumns = false.
EDIT:
There is another mistake in you code. You add the same instance of the object oClass 3 times. Use oClass = new Class(); before initializing a new person.

How to use get and set for array element in C#?

I have the following class:
public class test
{
private int i;
public test(int in)
{
i = in;
}
public int testint;
{
get { return i; }
set { i = testint; }
}
}
And the following code:
test[] data = new test[3];
for(int j = 0; j < 3; j++)
{
data[i] = new test(0);
data[i].testint = int.Parse(Console.ReadLine());
}
Console.WriteLine(test[0].testint);
Console.WriteLine(test[1].testint);
Console.WriteLine(test[2].testint);
When I run this program and type in 1, 2, 3 as the input, the output is 0, 0, 0. I don't understand why the get or set seem to be not working. If I initialize the array elements with a value other than 0, the output will be that. The data[i].testint = int.Parse(Console.ReadLine()); seems to not be working. How would I go about doing something like that?
Change the set method to this:
public int testint
{
get { return i; }
set { i = value; }
}
You setter is incorrect. It should be:
set { i = value; }
You had:
set { i = testint; }
Which only triggers the getter, which gets from i, so in the end your setter was doing i = i .
In a setter, the value keyword contains the new candidate value for the property. value's type equals the property's. I say candidate value because you can validate it and choose to not apply it.
In your case, you were not applying the value.
Update
Also, when defining getters and setters, no semicolon should be used. Code, then, would look like this:
public int testint
{
get { return i; }
set { i = value; }
}
I see two errors in this code:
public int testint;
{
get { return i; }
set { i = testint; }
}
There should be no semicolon after testint at the top. Also, set needs to assign using value, like this:
public int testint
{
get { return i; }
set { i = value; }
}
Change your setter to say:
set { i = value; }
value corresponds to the value you send to set the variable.
Here's simple way.
public int TestInt {get; set;}

Categories

Resources