C# array within an object within an array - c#

Here is a simplified version of my code:
class House
{
private string owner;
private int[] roomArea = new int[10];
public string Owner { get; set; }
public int[] RoomArea { get; set; }
}
class Program
{
static void Main(string[] args)
{
House[] london = new House[100];
for (int i = 0; i < 100; i++)
{
london[i] = new House();
}
london[0].Owner = "Timmy";
london[0].RoomArea[0] = 15; // Error points to this line
Console.WriteLine("Room 1 in " + london[0].Owner + "s house has the area of " + london[0].RoomArea[0] + "square meters");
}
}
I get the following error:
Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object.
I've looked at this this question/solution, yet I can't pinpoint what's exactly wrong with my code.

You need to initialize RoomArea. Even though you initialize inside the class it is creating it's own member , but in order to add values you need to initialize it
london[0].RoomArea = new int[10];
london[0].RoomArea[0] = 15;

Related

Need to change values in classes without changing its reference

I am currently making an application which tracks information on players and monsters for a tabletop game.
Currently I've got classes for "Monsters". This class contains information such as its name, maxHP, speed, attacks etc. I've managed to make a Database which contains the default values for each type of monster. What I currently need to do is make it possible to change things such as name (Monster > Monster 1, Monster 2 etc), change its HP, and some other things.
I understand that I need to make a copy of such, but I am uncertain on how to do this.
What I currently tried is the following:
public class DatabaseService
{
public List<Player> Players { get; set; }
public List<Monster> AllMonsters { get; set; }
public List<Monster> ActiveMonsters = new List<Monster>();
public bool RollForHP = false;
//Main Database Service
public DatabaseService()
{
Players = GetPlayers();
AllMonsters = GetAllMonsters();
}
public void DoStuff()
{
AddMonsterByName("Goblin", 2);
AddMonsterByName("Adult White Dragon", 1);
AddMonsterByName("Duergar", 4);
foreach (Monster monster in ActiveMonsters) { Console.WriteLine(monster.Name); }
}
//Converts the .json list with all players to Classes, which are then stored in the list "Players" if the "IsInParty" is true
private List<Player> GetPlayers()
{
var path = #"C:\Users\MyName\source\repos\DndAdvancedInitiativeTracker\Logic\Database\Players.json";
var json = File.ReadAllText(path);
var players = JsonConvert.DeserializeObject<List<Player>>(json);
List<Player> inPartyPlayers = new List<Player>();
foreach (var player in players)
{
if (player.IsInParty == true) { inPartyPlayers.Add(player); }
}
return inPartyPlayers;
}
//Converts the .json list with all monsters to Classes, which are then stored in the list "AllMonsters"
private List<Monster> GetAllMonsters()
{
var path = #"C:\Users\MyName\source\repos\DndAdvancedInitiativeTracker\Logic\Database\Monsters.json";
var json = File.ReadAllText(path);
var monsters = JsonConvert.DeserializeObject<List<Monster>>(json);
return monsters;
}
//Adds a given monster to the "ActiveMonsters" list
public void AddMonsterByName(string monsterName, int amountOfMonsters)
{
for (int i = 0; i < amountOfMonsters; i++)
{
List<Monster> DatabaseCopy = AllMonsters.Clone();
DatabaseCopy = AllMonsters;
Monster monster = DatabaseCopy.Find(x => x.Name == monsterName);
Console.WriteLine(monster.Name);
var number = CheckIfNameExistsInList(monsterName);
monster.Name = monsterName + " " + (number + i).ToString();
ActiveMonsters.Add(monster);
}
}
private int CheckIfNameExistsInList(string monsterName)
{
var counter = 1;
foreach (var monster in ActiveMonsters)
{
if (monster.Name.Contains(monsterName))
{
counter += 1;
}
}
return counter;
}
}
In the "DoStuff" Method, I try to add 2 goblins, then a dragon, then a goblin again. The first goblin is named to "Goblin 1" correctly, but the second loop fails, because the AllMonsters' name for goblins is now "Goblin 1" because of the reference type, therefore, the second "Goblin" search in AllMonsters is never found, and returns null.
I'm not sure why you're copying your database (and doing so for every iteration of a for loop which is quite wasteful), but your current check code CheckIfNameExistsInList will always return 1 even if there are no matches in the list.
You can simplify your AddMonstersByName (and use a simple check for previous monster entries) as follows:
public void AddMonstersByName(string name, uint number = 1)
{
var count = AllMonsters.Count(x => x.Name.Contains(name));
for (var i = 1; i <= number; i++)
{
var num = count + i;
AllMonsters.Add(new Monster(){Name= name+num.ToString()});
}
}
This was tested in a simple Console App:
var dataService = new DataService();
dataService.AddMonstersByName("Goblin", 2);
dataService.AddMonstersByName("Dragon", 2);
dataService.AddMonstersByName("Goblin", 2);
foreach (var monster in dataService.AllMonsters)
{
Console.WriteLine($"{monster.Name}");
}
where
public class DataService
{
public List<Monster> AllMonsters = new List<Monster>();
public void AddMonstersByName(string name, uint number = 1)
{
var count = AllMonsters.Count(x => x.Name.Contains(name));
for (var i = 1; i <= number; i++)
{
var num = count + i;
AllMonsters.Add(new Monster(){Name= name+num.ToString()});
}
}
}
public class Monster
{
public string Name { get; set; }
}

I got this error CS0103 and I don't know if this is from C# extension or if I forget to put something

I don't know if this is an error with the C# extension or I just forgot something.
I was trying to make a health base system so I convert into a string to print the number then back to int, to its original form.
FYI this some of my code, not all of it another thing I know their other forms but it wasn't looking for.
Example 1
example 2
class Conehead_Wizzard
{
public string name;
public string ConeHead_Powerful_spells;
public int slots;
public float Level_Up;
public int Player_Health;
public int Chance;
public int b;
public int c;
public Conehead_Wizzard(string _name, string _ConeHead_Powerful_spells,
int _Player_Health)
{
name = _name;
ConeHead_Powerful_spells = _ConeHead_Powerful_spells;
slots = 5;
Level_Up = 1.2f;
Player_Health = 1000;
b = 100;
void Damage_Chance ()
{
Random Chance_ = new Random();
int Chance = Chance_.Next(0, 100);
if (Chance > 99)
{
System.Console.WriteLine(Player_Health - b);
System.Console.WriteLine("you lost" + Player_Health + "of your health");
Player_Health--;
string a = Convert.ToString(Player_Health);
}
else
{
System.Console.WriteLine("Miss!, next player");
c = Convert.ToInt16(Player_Health);
}
}
}
}
class Program
{
static void Main(string[] args)
{
Conehead_Wizzard wizzard = new Conehead_Wizzard("Cone_Head ",
"The Cone of time &" + " Cone of shield", Player_Health);
}
}
You haven't declared the variable Player_Health in the Main method. Did you maybe intend to do something as follows:
static void Main(string[] args)
{
int Player_Health = 1000;
Conehead_Wizzard wizzard = new Conehead_Wizzard("Cone_Head ", "The Cone of time &" + " Cone of shield", Player_Health);
}
Although this should allow you to compile, be aware, the constructor isn't using the value passed into _Player_Health. It just sets wizzard.Player_Health to 1000. If you want to use it, you need to change your constructor to something like this:
public Conehead_Wizzard(string _name, string _ConeHead_Powerful_spells, int _Player_Health)
{
name = _name;
ConeHead_Powerful_spells = _ConeHead_Powerful_spells;
slots = 5;
Level_Up = 1.2f;
Player_Health = _Player_Health;
b = 100;
}

Getting an error when trying to set data in nested classes

I have created some nested classes but don't unterstand how to set the variables in the classes. My code so far only gives me a error:
System.NullReferenceException: Object reference not set to an instance of an object
Code:
class Felddaten
{
public string data;
}
class Feld
{
public string fieldName;
public Felddaten[] fieldData;
}
class Tabelle
{
public string tableName;
public Feld[] field;
}
class Program
{
static void Main(string[] args)
{
Tabelle table = new Tabelle();
table.tableName = "T100";
RFCConnector connector = new RFCConnector();
connector.getFieldNames(table.tableName, out List<string> fieldN);
table.field = new Feld[fieldN.Capacity];
for (int i = 0; i < fieldN.Capacity; i++)
{
table.field[0].fieldName = fieldN[0];
}
}
}
The error is at this line of code:
table.field[0].fieldName = fieldN[0];
You have only initialized the array table.field, not the ITEMS in the array. You need to initialize each item before you can access its members:
for(int i=0; i<table.field.Length; i++)
table.field[i] = new Feld();

run a FOR loop to create 4 plumbers from the default constructor c#

As you see in the title above, i need to run a FOR loop to create 4 plumbers from the default constructor. After they are created (within the FOR loop), change their names, add them to the employee list and display in listbox. So basically, plumbers is actually a list declared in another class called EmployeeList. Wehn i tried changing their names to random ones, i get like an error msg saying 'Index is out of range'. Can someone help me with this?
Form Code
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//create class-level employee list
EmployeeList plumbers = new EmployeeList();
private void Form1_Load(object sender, EventArgs e)
{
//run a for loop to create 4 plumbers from the default constructor.
for (int i = 0; i < plumbers.Count; i++)
plumbers[i] = new Employee();
//After they are created (within the FOR loop), change their names,
//plumbers[0].Name = "Nicole Fernandez";
//add them to the employee list
//display in listbox
foreach (Employee item in plumbers.Employees)
{
lstDisplay.Items.Add(item.DisplayData());
}
}
Employee List Class Code
class EmployeeList
{
//use private access modifier to create a list of employee
private List<Employee> employees = new List<Employee>();
public List<Employee> Employees
{
get { return employees; }
set { employees = value; }
}
//return the count of the employee list, use lambda operator
public int Count => employees.Count();
//create default constructor
public EmployeeList() { }
//create a method that adds employee sent to the list. No return value
public void AddEmp(Employee emp)
{
employees.Add(emp);//add employee to the list
}
//create employee from data sent. No return value
public void AddEmp(string inName, int inID, decimal inHourlyWage)
{
//declare a variable
Employee emp = new Employee(inName, inID, inHourlyWage);
//call the other AddEmp
AddEmp(emp);
}
//create a method that deletes employee from the list. No return value
public void DeleteEmp(Employee emp) => employees.Remove(emp);
//insert employee at the index
public void InsertEmp(Employee emp, int index) => employees.Insert(index, emp);
//create an indexer
public Employee this[int i]
{ //q12 - indexer property with exception
get
{
if (i < 0 || i >= Count)
throw new ArgumentOutOfRangeException(i.ToString());
return employees[i];
}
set { employees[i] = value; }
}
}
Employee Class Code
class Employee
{
//use auto-implemented property
public int ID { get; set; }
public string Name { get; set; }
public decimal HourlyWage { get; set; }
public decimal TotalPay { get; set; }
//create static integer that starts at 1
private static int NextID = 1;
//create a default constructor with default values
public Employee()
{
ID = NextID++;
Name = "John Doe";
HourlyWage = 15.25m;
TotalPay = 0.0m;
}
//create the custom constructor sending in 3 parameters
public Employee(string inName, int inID, decimal inHourlyWage)
{
Name = inName;//set name, no validation is required
//validate ID is between 1 and 250. if not, set to nextID available
if (inID <= 1 && inID >= 250)
NextID = inID;
//validate hourly wage is between 12.50 and 20. If not, set to 15.25
if (inHourlyWage <= 12.50m && inHourlyWage >= 20.0m)
inHourlyWage = 15.25m;
TotalPay = 0;//set total pay to 0
}
public string DisplayData() => ID + "\t" + Name + "\t" + HourlyWage.ToString("c") + "\t" + TotalPay.ToString("c");
}
First, if you want to create a list of 4 plumbers using a loop, then you need the loop to iterate 4 times. This is normally done by setting the initial counter value to 0, then looping while it is less than the number you want:
for (int i = 0; i < 4; i++)
Also, your plumbers object is of type EmployeeList, but you're trying to access it with an indexer as if it's a List or an Array. Instead, you should use the method you created to add new employees:
// Run a for loop to create 4 plumbers from the default constructor.
for (int i = 0; i < 4; i++)
{
plumbers.AddEmp(new Employee());
}
Since there doesn't appear to be any public method to update an existing plumber, we can just access the Employees list directly to rename the plumbers. There are a couple of ways to do it. One would be to use a loop and use part of the loop counter in the name:
// After they are created (within the FOR loop), change their names
for(int i = 0; i < plumbers.Employees.Count; i++)
{
plumbers.Employees[i].Name = string.Format("Plumber #{0}", i);
}
Another way is to do it by hand, giving each plumber a normal name:
plumbers.Employees[0].Name = "Nicole";
plumbers.Employees[1].Name = "Rufus";
plumbers.Employees[2].Name = "Mark";
plumbers.Employees[3].Name = "John";
Or, if you want to be really fancy, you can generate a list of names (I pulled these from the top baby names of 2016), then for each plumber grab a random name from the list and assign it (and remove it from the list so the plumbers all have unique names):
//After they are created (within the FOR loop), change their names
// Generate a list names
var nameCandidates = new List<string>
{
"Olivia", "Amelia", "Charlotte", "Ava", "Isla", "Arabella", "Aurora",
"Adeline", "Penelope", "Eleanor", "Ezra", "Asher", "Atticus",
"Declan", "Oliver", "Silas", "Milo", "Levi", "Henry", "Wyatt"
};
// Loop through each plumber and choose a random name
var rnd = new Random();
foreach(var plumber in plumbers.Employees)
{
// Choose a random name, assign it, and remove it from candidates
var nameIndex = rnd.Next(nameCandidates.Count);
plumber.Name = nameCandidates[nameIndex];
nameCandidates.RemoveAt(nameIndex);
}

How do I create an array of objects in constructor?

I have two classes:
game
element
I want to be able to define an array of element objects in a game object. When I try this I get the warning message "..is never assigned to, and will always have its default value null"; in the local variables in the debugger I can see that the array exists, but all entries are null. The class Element works as I would expect. If I assign element objects to an array in Main it works, but not when I move the code to the Game constructor.
What am I doing wrong? I'm new to C# so it could be something very basic. Code below. Many thanks.
class Element
{
public Element()
{
elements = new List<int>(3);
elements.Add(1);
elements.Add(2);
elements.Add(3);
}
List<int> elements;
public void PrintElement()
{
for (int i = 0; i < 3; i++)
{
Console.WriteLine("Element {0}: {0}", i + 1, elements[i]);
}
}
}
class Game
{
public Game()
{
Element1 = new Element();
Element2 = new Element();
Element3 = new Element();
Element[] ThisGame = new Element[3];
ThisGame[0]= Element1;
ThisGame[1] = Element2;
ThisGame[2] = Element3;
}
public Element[] ThisGame;
private Element Element1;
private Element Element2;
private Element Element3;
public void PrintGameElement(int number)
{
ThisGame[number].PrintElement();
}
}
class Program
{
Game MyGame;
static void Main(string[] args)
{
Game MyGame = new Game();
MyGame.PrintGameElement(2);
Console.Read();
}
}
In Game, you are re-declaring ThisGame.
Change
Element[] ThisGame = new Element[3];
to
ThisGame = new Element[3];
Your Game constructor should look like this:
public Game()
{
Element1 = new Element();
Element2 = new Element();
Element3 = new Element();
ThisGame = new Element[3];
ThisGame[0]= Element1;
ThisGame[1] = Element2;
ThisGame[2] = Element3;
}
You need to set the list object to something when you initialize it.
List<int> elements = null;
OR
List<int> elements = new List<int>();
look at this code it may help you to make some order in your code:
Element class :
class Element
{
//property on element to save element data
public string ElementData { get; set; }
public Element(string data)
{
ElementData = data;
}
}
Game class :
class Game
{
//property on Game to save all elements
Element[] Elements { get; set; }
public Game(Element[] elements)
{
Elements = elements;
}
public void PrintGameElements()
{
foreach (var element in Elements)
{
Console.WriteLine(element.ElementData);
}
}
public void PrintElement(int index)
{
Console.WriteLine(Elements[index].ElementData);
}
}
Main function that initialize the array and pass it to the game :
static void Main(string[] args)
{
//initialize the array
var elements = new[]
{
new Element("data x"),
new Element("data y"),
new Element("data z")
};
//pass the elements to the game
var game = new Game(elements);
//print the second element
game.PrintElement(1);
//print all elements
game.PrintGameElements();
Console.ReadKey();
}
}

Categories