Creating a collection that stores objects of derived classes [duplicate] - c#

This question already has answers here:
Unsure about parameters when calling base constructor from derived class
(2 answers)
Closed 2 years ago.
I'm creating a .NET core menu-based console app that allows you to add and manage players from different sports.
My Player class:
abstract class Player
{
enum PlayerType
{
HockeyPlayer,
BacketballPlayer,
BaseballPlayer
}
public abstract void Points();
private long playerId;
private string playerName;
private string teamName;
private int gamesPlayed;
public long PlayerId
{
get { return playerId; }
set { playerId = value; }
}
public string PlayerName
{
get { return playerName; }
set { playerName = value; }
}
public string TeamName
{
get { return teamName; }
set { teamName = value; }
}
public int GamesPlayed
{
get { return gamesPlayed; }
set { gamesPlayed = value; }
}
}
class HockeyPlayer : Player
{
private int assists;
private int goals;
public override void Points()
{
int totalPoints = assists + (2 * goals);
}
public int Assists
{
get { return assists; }
set { assists = value; }
}
public int Goals
{
get { return goals; }
set { goals = value; }
}
}
class BasketballPlayer : Player
{
private int fieldGoals;
private int threePointers;
public override void Points()
{
int totalPoints = (fieldGoals - threePointers) + (2 * threePointers);
}
public int FieldGoals
{
get { return fieldGoals; }
set { fieldGoals = value; }
}
public int ThreePointer
{
get { return threePointers; }
set { threePointers = value; }
}
}
class BaseballPlayer : Player
{
private int runs;
private int homeRuns;
public override void Points()
{
int totalPoints = (runs - homeRuns) + (2 * homeRuns);
}
public int Runs
{
get { return runs; }
set { runs = value; }
}
}
And a snippet of my main class:
class Controller
{
static void Main(string[] args)
{
List<Player> players = new List<Player>()
{
new HockeyPlayer(1, "Mitch Marner", "Toronto Maple Leafs", 5)
};
In the controller I am trying to populate the list with some sample data, but obviously I don't have a constructor in my derived HockeyPlayer class. How do I create a constructor for HockeyPlayer where the arguments are 'playerId', 'playerName', 'teamName', and 'gamesPlayed' which come from the parent class. I feel like I'm missing something very simple here.

A funny thing is that you are using 'object initialization' for the list, but trying to call the constructor of HockeyPlayer, where you also could use the object initialization method.
The object initialization is executed after the constructor (assigning properties) but enables construction and property initialization in one single statement
For example:
List<Player> players = new List<Player>()
{
new HockeyPlayer(1, "Mitch Marner", "Toronto Maple Leafs", 5);
};
List<Player> players = new List<Player>()
{
new HockeyPlayer
{
PlayerId = 1,
PlayerName = "Mitch Marner",
TeamName = "Toronto Maple Leafs",
GamesPlayed = 5
}
};
Constructors are usefull when certain parameters are mandatory. This way you force an initial value for a field/property.
Object initializers is just syntactic sugar for constructing and assigning properties. With a big difference (like i said) an object initializer can be treated as a single statement. (therefor you can pass it as an argument to a function.)
var player = new HockeyPlayer
{
PlayerId = 1,
PlayerName = "Mitch Marner",
TeamName = "Toronto Maple Leafs",
GamesPlayed = 5
}
VS
var player = new HockeyPlayer();
player.PlayerId = 1;
player.PlayerName = "Mitch Marner";
player.TeamName = "Toronto Maple Leafs";
player.GamesPlayed = 5;

Related

how do i change the value of an object

here is my main method:
string input = Console.ReadLine(); // 2006 2000 false 1000 500 Windows
List<string> inputs = input.Split(" ").ToList();
Computer one = new Computer(int.Parse(inputs[0]), int.Parse(inputs[1]), bool.Parse(inputs[2]), double.Parse(inputs[3]), double.Parse(inputs[4]), inputs[5]);
one.Print(); // 2006, 2000, false, 1000, 500, Windows
input = Console.ReadLine(); //changeOperatingSystem
if (input == "changeOperatingSystem")
{
string newOperationSystem = Console.ReadLine(); //Linux
Computer two = new Computer(newOperationSystem);
}
one.Print(); //2006, 2000, false, 1000, 500, Linux
the "//" marks what the input and the output look like.
This is my Computer.cs:
private int years;
private int price;
private bool isNotebook;
private double hardDiskMemory;
private double freeMemory;
private string operationSystem;
private string newOperationSystem;
public Computer(int years, int price, bool isNotebook, double hardDiskMemory, double freeMemory, string operationSystem)
{
Years = years;
Price = price;
IsNotebook = isNotebook;
HardDiskMemory = hardDiskMemory;
FreeMemory = freeMemory;
OperationSystem = operationSystem;
}
public Computer(string newOperationSystem)
{
OperationSystem = newOperationSystem;
}
public int Years
{
get { return years; }
set
{
years = value;
}
}
public int Price
{
get { return price; }
set
{
price = value;
}
}
public bool IsNotebook
{
get { return isNotebook; }
set
{
isNotebook = value;
}
}
public double HardDiskMemory
{
get { return hardDiskMemory; }
set
{
hardDiskMemory = value;
}
}
public double FreeMemory
{
get { return freeMemory; }
set
{
freeMemory = value;
}
}
public string OperationSystem
{
get { return operationSystem; }
set
{
operationSystem = value;
}
}
public string NewOperationSystem
{
get { return NewOperationSystem; }
set
{
newOperationSystem = value;
}
}
public void Print()
{
Console.WriteLine($"{years}, {price}, {isNotebook}, {hardDiskMemory}, {FreeMemory}, {operationSystem}");
}
what I want this program to do is whenever the input submitted by the user is "changeOperationSystem" the program gives the user another input where they submit the new Operation system for the pc. Then with the constructor, the Computer.Cs receives the string newOperationSystem, which then should replace the value operationSystem as I tried to do in the constructor: OperationSystem = newOperationSystem, but it doesn't work. I am stil learning classes so don't go hard on me.
It seems to me you are trying to change one property of a class. All you have to do is use the property set method
one.OperationSystem = newOperationSystem;
and remove the property NewOperationSystem altogether.
Here is a bare bones skeleton code of instantiating a class with a constructor and then changing one of the properties
public class Foo
{
private int _a;
private string _b;
private readonly float _c;
public Foo(int a, string b, float c)
{
_a = a;
_b = b;
_c = c;
}
public int A { get => _a; set => _a = value; }
public string B { get => _b; set => _b = value; }
public float C => _c;
public override string ToString()
{
return $"{_a}, {_b}, {_c}";
}
}
class Program
{
static void Main(string[] args)
{
Foo one = new Foo(100, "Philip", 0.75f);
Console.WriteLine(one);
//100, Philip, 0.75
one.B = "Spencer";
Console.WriteLine(one);
//100, Spencer, 0.75
}
}
Another feature of the code above is that there is no need to create a .Print() method, if you can take advantage of the built-in .ToString() which gets called automatically during a Console.WriteLine() or any other operations that require a string input from my class.
Finally, I added a read-only property C to demonstrate that this design is possible. You will not be able to write one.C = 0.25f; since the property is read-only.

cannot add object to list, add does not exist in current context

I am trying to create a simple radio station class. The RadioPlayer class will store a List of radio stations. Although for some reason I can not add radio stations to a List of radio stations. Can anyone tell me why? It says
"stations.Add does not exist in the current context"
I am also using System.Collections.Generic.
namespace CATest
{
public interface IStreamable
{
}
public enum Genre
{
General,
Music,
News
}
public class RadioStation : IStreamable
{
public const double MinFreq = 87.5;
public const double MaxFreq = 108;
private double frequency;
public string StationName { get; set; }
public Genre Genre { get; set; }
public double Frequency
{
get
{
return frequency;
}
set
{
//validate frequency
if(value > MinFreq && value < MaxFreq)
{
frequency = value;
}
else
{
throw new ArgumentException("Frequency must be between 87.5 and 108");
}
}
}
public override string ToString()
{
return $"Station Name: {StationName} \nStation Genre: {Genre} \nStation Frequency: {Frequency}";
}
}
public class RadioPlayer
{
private List<RadioStation> stations = new List<RadioStation>();
stations.Add(new RadioStation() { Frequency = 100, StationName = "Radio2", Genre = Genre.Music });
}
}
You need to do this inside a method or constructor or somewhere. You cannot place this just within the class declaration.
public void AddStations(RadioStation station)
{
stations.Add(station);
}
you cant add in the class level you must declare method and this method do the behaviour that you need meanwhile you can define the list in class level but any operation should happens inside method or contractor
public class RadioPlayer
{
List<RadioStation> stations = new List<RadioStation>();
public void DoSomething()
{
stations.Add(new RadioStation() { Frequency = 100, StationName = "Radio2", Genre = Genre.Music });
}
}
I would suggest that you do it inside the constructor.
Here's the implementation
public class RadioPlayer
{
public RadioPlayer()
{
stations = new List<RadioStation>();
stations.Add(new RadioStation() { Frequency = 100, StationName = "Radio2", Genre = Genre.Music });
}
private List<RadioStation> stations;
}
You aren't allowed to use Add method at the class context. You can use List initializer to add an item(s) to list at creation time
private List<RadioStation> stations = new List<RadioStation>()
{
new RadioStation() { Frequency = 100, StationName = "Radio2", Genre = Genre.Music }
};

Polymorphism and Interfaces in C#

Create three small classes unrelated by inheritance—classes Building, Car and Bicycle. Write an interface ICarbonFootprint with a GetCarbonFootprint method. Have each of your classes implement that interface, so that its GetCarbonFootprint method calculates an appropriate carbon footprint for that class (check out a few websites that explain how to calculate carbon footprints). Write an app that creates objects of each of the three classes, places references to those objects in List, then iterates through the List, polymorphically invoking each object’s GetCarbonFootprint method. Constructor of Car initialize “gallon of gas”, and the Building constructor will initialize buiding-square-footage.
how to calculate carbon-footprint
One gallon of gas yields 20 pounds of CO2 for a car
Multiply the square footage by 50 for a building
None for a bicycle
My instructor's code:
public static void Main(string[] args)
{
ICarbonFootprint[] list = new ICarbonFootprint[3];
// add elements to list
list[0] = new Bicycle();
list[1] = new Building(2500);
list[2] = new Car(10);
// display carbon footprint of each object
for (int i = 0; i < list.Length; i++)
list[i].GetCarbonFootprint();
} // end Main
}
My code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Miller
{
class Program
{
static void Main(string[] args)
{
Bicycle bike = new Bicycle();
Building b = new Building();
Car car = new Car();
List<ICarbonFootprint> list = new List<ICarbonFootprint>();
list.Add(bike);
list.Add(b);
list.Add(car);
int totalCarbon = 0;
foreach (var item in list)
{
totalCarbon += item.GetCarbonFootprint();
Console.WriteLine("{0} has a footprint of: {1}", item, item.GetCarbonFootprint());
}
Console.WriteLine("Total footprint is: {0}", totalCarbon);
Console.ReadKey();
}
}
public class Bicycle : ICarbonFootprint
{
private string _make;
private string _model;
public string Make
{
get { return _make; }
set { _make = value; }
}
public string Model
{
get { return _model; }
set { _model = value; }
}
public int GetCarbonFootprint()
{
return 10;
}
public override string ToString()
{
return string.Format("Bike");
}
}
public class Building : ICarbonFootprint
{
private string _address;
public string Address
{
get { return _address; }
set { _address = value; }
}
public int GetCarbonFootprint()
{
return 2000;
}
public override string ToString()
{
return string.Format("Building");
}
}
public class Car : ICarbonFootprint
{
private string _make;
private string _model;
public string Make
{
get { return _make; }
set { _make = value; }
}
public string Model
{
get { return _model; }
set { _model = value; }
}
public int GetCarbonFootprint()
{
return 1500;
}
public override string ToString()
{
return string.Format("Car");
}
}
public interface ICarbonFootprint
{
int GetCarbonFootprint();
}
}
Me integrating my instructor's code (lines 12-23 changed AKA class Program was the only thing changed):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Miller
{
class Program
{
public static void Main(string[] args)
{
ICarbonFootprint[] list = new ICarbonFootprint[3];
// add elements to list
list[0] = new Bicycle();
list[1] = new Building(2500);
list[2] = new Car(10);
// display carbon footprint of each object
for (int i = 0; i < list.Length; i++)
list[i].GetCarbonFootprint();
} // end Main
}
public class Bicycle : ICarbonFootprint
{
private string _make;
private string _model;
public string Make
{
get { return _make; }
set { _make = value; }
}
public string Model
{
get { return _model; }
set { _model = value; }
}
public int GetCarbonFootprint()
{
return 10;
}
public override string ToString()
{
return string.Format("Bike");
}
}
public class Building : ICarbonFootprint
{
private string _address;
public string Address
{
get { return _address; }
set { _address = value; }
}
public int GetCarbonFootprint()
{
return 2000;
}
public override string ToString()
{
return string.Format("Building");
}
}
public class Car : ICarbonFootprint
{
private string _make;
private string _model;
public string Make
{
get { return _make; }
set { _make = value; }
}
public string Model
{
get { return _model; }
set { _model = value; }
}
public int GetCarbonFootprint()
{
return 1500;
}
public override string ToString()
{
return string.Format("Car");
}
}
public interface ICarbonFootprint
{
int GetCarbonFootprint();
}
}
So, replacing my code for class Program with my instructor's code, I received the following errors:
Program.cs(51,23,51,41): error CS1729: 'Miller.Building' does not contain a constructor that takes 1 arguments
Program.cs(52,23,52,34): error CS1729: 'Miller.Car' does not contain a constructor that takes 1 arguments
Now, because the last two days before Spring break were cancelled due to the weather (snow), we weren't able to discuss. My code seems to do what the directions ask, but I would like to get my instructor's code for class Program working with my code. Could someone help me with these errors possibly?
There are a few issues with your code.
First up you need to include the constructors to make the code compile.
For Building this would look like:
private int squareFootage;
public Building(int squareFootage)
{
this.squareFootage = squareFootage;
}
And for Car this would look like:
private int gasGallons;
public Car(int gasGallons)
{
this.gasGallons = gasGallons;
}
Next, you're not following the rules for calculating the carbon footprint.
They should be:
//Bicycle
public int GetCarbonFootprint()
{
return 0;
}
//Building
public int GetCarbonFootprint()
{
return 50 * squareFootage;
}
//Car
public int GetCarbonFootprint()
{
return 20 * gasGallons;
}
Finally, your instructor's code doesn't actually display any results. The code in the for loop should be changed to be Console.WriteLine(list[i].GetCarbonFootprint()); if this is a console app.
So, all up the code should look like this:
public static void Main(string[] args)
{
ICarbonFootprint[] list = new ICarbonFootprint[3];
// add elements to list
list[0] = new Bicycle();
list[1] = new Building(2500);
list[2] = new Car(10);
// display carbon footprint of each object
for (int i = 0; i < list.Length; i++)
Console.WriteLine(list[i].GetCarbonFootprint());
}
public class Bicycle : ICarbonFootprint
{
public string Make { get; set; }
public string Model { get; set; }
public int GetCarbonFootprint()
{
return 0;
}
}
public class Building : ICarbonFootprint
{
private int squareFootage;
public Building(int squareFootage)
{
this.squareFootage = squareFootage;
}
public string Address { get; set; }
public int GetCarbonFootprint()
{
return 50 * squareFootage;
}
}
public class Car : ICarbonFootprint
{
private int gasGallons;
public Car(int gasGallons)
{
this.gasGallons = gasGallons;
}
public string Make { get; set; }
public string Model { get; set; }
public int GetCarbonFootprint()
{
return 20 * gasGallons;
}
}
public interface ICarbonFootprint
{
int GetCarbonFootprint();
}
I've opted to short-cut the property definitions rather than implement them with fields.
The output is:
0
125000
200
You should write constructors for Building and Car like next:
public Building(int MyValue)
{
...
}
and your code will work fine.
Suggestion: Car and Bicycle shares properties, and the ICarbonFootprint implementation, so you can create a base class with an abstract method. Also the GetCarbonFootprint from ICarbonFootprint interface must be type of System.Double.
public interface ICarbonFootprint
{
int GetCarbonFootprint();
}
public class Building : ICarbonFootprint
{
public int BuildingSquareFootage { get; set; }
public string Address { get; set; }
public Building(int buildingSquareFootage, string address)
{
BuildingSquareFootage = buildingSquareFootage;
Address = address;
}
public int GetCarbonFootprint()
{
return BuildingSquareFootage * 50;
}
public override string ToString()
{
return string.Format("Building");
}
}
public abstract class CarBicycleBase : ICarbonFootprint
{
public string Make { get; set; }
public string Model { get; set; }
protected CarBicycleBase(string make, string model)
{
Make = make;
Model = model;
}
public abstract int GetCarbonFootprint();
}
public class Bicycle : CarBicycleBase
{
public Bicycle(string make, string model)
: base(make, model) { }
public override int GetCarbonFootprint()
{
return 0;
}
public override string ToString()
{
return string.Format("Bike");
}
}
public class Car : CarBicycleBase
{
public int GallonOfGas { get; set; }
public Car(int gallonOfGas, string make, string model)
: base(make, model)
{
GallonOfGas = gallonOfGas;
}
public override int GetCarbonFootprint()
{
return GallonOfGas * 20;
}
public override string ToString()
{
return string.Format("Car");
}
}
Example:
...
var list = new List<ICarbonFootprint>(3)
{
new Car(10, "...", "..."),
new Bicycle("...", "..."),
new Building(20, "...")
};
foreach (ICarbonFootprint item in list)
item.GetCarbonFootprint();
...
I hope it helps.

How do you XMLSerialize a more complex class in c#?

hello I want to serialize a class in C# with a XMLserializer. The Compiler says that Room (myClass) is not primitive (i am using Unity3d) and therefor can not be serialized. The problem is that the most Tutorial are only for simple classes with a few simple fields. Can you help me changs Room to be serializable?
[Serializable]
public class Room
{
public Room()
{
m_id = "test";
m_section = Areas.PublicSec;
m_connections = null;
m_size = 10;
}
public Room(string _id, Areas _section, List<string> _connections, int _size)
{
// f.e. Bathroom
m_id = _id;
// private, public or hallway filled with the enum Areas
m_section = _section;
// list of rooms that have or will have a Connection
if (_connections != null)
{
m_connections = _connections;
}
else
{
m_connections = new List<string>();
}
//? Desired minium size of the room
m_size = _size;
}
private string m_id;
public string id
{
get { return m_id; }
set { m_id = value;}
}
private Areas m_section;
public Areas Section
{
get { return m_section; }
set { m_section = value; }
}
private List<string> m_connections;
[XmlArray("m_connections")]
public List<string> Connections
{
get { return m_connections; }
set { m_connections = value; }
}
private int m_size;
public int Size
{
get { return m_size; }
set { m_size = value; }
}
}
My XMLSerializer works with simple classes but not with this one.

Class placing a instance of its self in static list located in the class

Is this a common way to store instances in a list that can be accessed by any class. Are there any better Techniques to achieving this?
class fish
{
string species = "Gold Fish";
int age = 1;
public static list<fish> Listholder = new list<fish>();
Listholder.add(this);
}
List<T> is not thread safe, so if you want to add/remove fishs from different threads you should use ConcurrentBag<T> instead.
For example:
public class Fish
{
public string Species { get; set; }
public int Age { get; set; }
private static System.Collections.Concurrent.ConcurrentBag<Fish> Aquarium = new System.Collections.Concurrent.ConcurrentBag<Fish>();
static Fish()
{
var goldFish = new Fish { Age = 1, Species = "Gold Fish" };
PutFishIntoAquarium(goldFish);
}
public static void PutFishIntoAquarium(Fish fish)
{
Aquarium.Add(fish);
}
public static void ClearAquarium()
{
Fish someFish;
while (!Aquarium.IsEmpty)
{
TryTakeFishOutOfAquarium(out someFish);
}
}
public static bool TryTakeFishOutOfAquarium(out Fish fish)
{
if (Aquarium.TryTake(out fish))
return true;
return false;
}
public static bool TryLookAtSomeFish(out Fish fish)
{
if (Aquarium.TryPeek(out fish))
return true;
return false;
}
}
I think what you're trying to get at is a way to store a globally accessible list of fish somewhere. I.e. to have a central repository of fish that all other classes get their fish from.
If this is so, there are other ways of doing this such as the Service/Repository pattern. Keep in mind that having a mutable public static field will make testing and re-usability harder.
a Class has Properties.
the class allows you to create objects.
class fish()
{
Private String _Type;
Private Int _Age;
Private String _Species;
Public Type
{
get _Type;
set _Type = Value;
}
Public Age
{
get _Age;
set _Age = Value;
}
Public Species
{
get _Species;
set _Species = Value;
}
public new(string Type, Int Age, String Species)
{
this.Type = Type;
this.Age = Age;
this.Species = Species;
}
}
//this is your new object.
Fish SunFish = New Fish("small", 9, "Sunfish");
after creating an object you can create a list of objects

Categories