Vehicle Object Array - C# - c#

I'm having trouble writing up some code. I'm not too sure where and how to write up the constructors and the accessors.
The activity I have to do is this:
Write 3 derived classes to allow a user to enter the details of three types of Vehicles with their attributes.
• Car (make, model, year, bodyType)
• Airplane (make, model, year, noEngines, engineType)
• Boat (make, model, year, length, hullType)
The 4th class is the base class Vehicle which contains the shared attributes and methods
Make all attributes either private (in derived classes) or protected (in base class) and write accessor methods for each attribute.
Write 2 constructors for each derived class. One with no arguments and the other which accepts the values of the attributes in the derived class as arguments.
Write a Console Application called Fleet.cs which creates and displays 2 of each Vehicle type
My code so far is as follows:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication5
{
class Vehicle
{
static void Main(string[] args)
{
}
class Car
{
protected string make
{
get
{
return make;
}
set
{
make = value;
}
}
protected string model
{
get
{
return model;
}
set
{
model = value;
}
}
protected int year
{
get
{
return year;
}
set
{
year = value;
}
}
protected string bodyType
{
get
{
return bodyType;
}
set
{
bodyType = value;
}
}
public bool isInitialized;
public Car()
{
isInitialized = true;
}
}
}
class Airplane
{
protected string make
{
get
{
return make;
}
set
{
make = value;
}
}
protected string model
{
get
{
return model;
}
set
{
model = value;
}
}
protected int year
{
get
{
return year;
}
set
{
year = value;
}
}
protected int numEngines
{
get
{
return numEngines;
}
set
{
numEngines = value;
}
}
protected int engineType
{
get
{
return engineType;
}
set
{
engineType = value;
}
}
}
class Boat
{
protected string make
{
get
{
return make;
}
set
{
make = value;
}
}
protected string model
{
get
{
return model;
}
set
{
model = value;
}
}
protected string year
{
get
{
return year;
}
set
{
year = value;
}
}
protected string length
{
get
{
return length;
}
set
{
length = value;
}
}
protected string hullType
{
get
{
return hullType;
}
set
{
hullType = value;
}
}
}
}

First part the OOP principles
Classes:
A class is a construct that enables you to create your own custom
types by grouping together variables of other types, methods and
events. A class is like a blueprint. It defines the data and behavior
of a type. If the class is not declared as static, client code can use
it by creating objects or instances which are assigned to a variable.
The variable remains in memory until all references to it go out of
scope. At that time, the CLR marks it as eligible for garbage
collection. If the class is declared as static, then only one copy
exists in memory and client code can only access it through the class
itself, not an instance variable. For more information, see Static
Classes and Static Class Members (C# Programming Guide). Unlike
structs, classes support inheritance, a fundamental characteristic of
object-oriented programming. For more information, see Inheritance (C#
Programming Guide).
Also objects are instances of classes.
Inheritance:
Inheritance, together with encapsulation and polymorphism, is one of
the three primary characteristics (or pillars) of object-oriented
programming. Inheritance enables you to create new classes that reuse,
extend, and modify the behavior that is defined in other classes. The
class whose members are inherited is called the base class, and the
class that inherits those members is called the derived class. A
derived class can have only one direct base class. However,
inheritance is transitive. If ClassC is derived from ClassB, and
ClassB is derived from ClassA, ClassC inherits the members declared in
ClassB and ClassA.
Derived class:
A class that was created based on a previously existing class (i.e., base class). A derived class inherits all of the member variables and methods of the base class from which it is derived.
Also called a derived type.
Method:
A method (or message) in object-oriented programming (OOP) is a
procedure associated with an object class. An object is made up of
behavior and data. Data is represented as properties of the object and
behavior as methods. Methods are also the interface an object presents
to the outside world. For example a window object would have methods
such as open and close. One of the most important capabilities that a
method provides is method overriding. The same name (e.g., area) can
be used for multiple different kinds of classes. This allows the
sending objects to invoke behaviors and to delegate the implementation
of those behaviors to the receiving object. For example an object can
send an area message to another object and the appropriate formula
will be invoked whether the receiving object is a rectangle,circle,
triangle, etc.
Attributes and properties:
"Fields", "class variables", and "attributes" are more-or-less the
same - a low-level storage slot attached to an object. Each language's
documentation might use a different term consistently, but most actual
programmers use them interchangeably. (However, this also means some
of the terms can be ambiguous, like "class variable" - which can be
interpreted as "a variable of an instance of a given class", or "a
variable of the class object itself" in a language where class objects
are something you can manipulate directly.)
"Properties" are, in most languages I use, something else entirely -
they're a way to attach custom behaviour to reading / writing a field.
(Or to replace it.)
So if you want to categorize them they are OOP(Object Oriented Programming) principles.
Second part:
Write a Console Application called Fleet.cs which creates and displays
2 of each Vehicle type.
So one way of doing this is creating vehicles as hardcoded. The other way is to ask user for vehicle details with Console.Readline(). Main method could look something like this.
static void Main(string[] args)
{
Vehicle v1 = new Vehicle { Make = "test1", Model = "model1", Year = 1996 };
Vehicle v2 = new Vehicle { Make = "test2", Model = "model2", Year = 1997 };
Console.WriteLine(v1);
Console.WriteLine(v2);
...
}
And then you would override the ToString() method for each class. Like this:
public override string ToString()
{
return string.Format("Vehicle is {0} and of model {1} and is made in {2}.", make, model, year);
}
Here you also can use base.ToString() to get the data of upper (base) class in the derivided class.
EDIT 1: User input:
So if you want the user input you could make program like this:
static void Main(string[] args)
{
//input
Vehicle v1 = new Vehicle();
Console.Write("Enter the make of 1st vehicle: ");
v1.Make = Console.ReadLine();
Console.Write("Enter the model of 1st vehicle: ");
v1.Model = Console.ReadLine();
Console.WriteLine("Enter the year of manufacturing for 1st vehicle:");
v1.Year = int.Parse(Console.ReadLine());
//output
Console.WriteLine("The data for 1st vehicle: ");
Console.WriteLine(v1);
...
}
Even better would be to create Input method in the class and calling it from Main program. So code would not be repeating itself.
Finished program
Vehicle.cs
using System;
class Vehicle
{
string make, model;
int year;
public string Make { get { return make; } set { make = value; } }
public string Model { get { return model; } set { model = value; } }
public int Year { get { return year; } set { year = value; } }
public Vehicle()
{
make = model = "Unknown";
year = 0;
}
public Vehicle(string make, string model, int year)
{
this.make = make;
this.model = model;
this.year = year;
}
public virtual void GetFromInput()
{
Console.Write("Enter the make of vehicle: ");
Make = Console.ReadLine();
Console.Write("Enter the model of vehicle: ");
Model = Console.ReadLine();
Console.WriteLine("Enter the year of manufacturing for vehicle: ");
Year = int.Parse(Console.ReadLine());
}
public override string ToString()
{
return string.Format("Vehicle is {0} and of model {1} and is made in {2}.", make, model, year);
}
}
Car.cs
using System;
class Car : Vehicle
{
string bodyType;
public string BodyType { get { return bodyType; } set { bodyType = value; } }
public Car() : base()
{
bodyType = "Unknown";
}
public Car(string make, string model, int year, string bodyType) : base(make, model, year)
{
this.bodyType = bodyType;
}
public override void GetFromInput()
{
base.GetFromInput();
Console.Write("Enter body type for the car: ");
BodyType = Console.ReadLine();
}
public override string ToString()
{
return base.ToString() + string.Format("This vehicle is a car with body type of {0}.", BodyType);
}
}
Airplane.cs
using System;
class Airplane : Vehicle
{
int noEngines;
string engineType;
public int NumberOfEngines{ get { return noEngines; } set { noEngines = value; } }
public string EngineType { get { return engineType; } set { engineType = value; } }
public Airplane() : base()
{
noEngines = 0;
engineType = "Unknown";
}
public Airplane(string make, string model, int year, int noEngines, string engineType) : base(make, model, year)
{
this.noEngines = noEngines;
this.engineType = engineType;
}
public override void GetFromInput()
{
base.GetFromInput();
Console.Write("Enter the number of engines on an airplane: ");
NumberOfEngines = int.Parse(Console.ReadLine());
Console.Write("Enter the engine type for the airplane: ");
EngineType = Console.ReadLine();
}
public override string ToString()
{
return base.ToString() + string.Format("This vehicle is an airplane with {0} engines and engine type of {1}.", NumberOfEngines, EngineType);
}
}
Boat.cs
using System;
class Boat : Vehicle
{
int length;
string hullType;
public int Length { get { return length; } set { length = value; } }
public string HullType { get { return hullType; } set { hullType = value; } }
public Boat() : base()
{
length = 0;
hullType = "Unknown";
}
public Boat(string make, string model, int year, int length, string hullType) : base(make, model, year)
{
this.length = length;
this.hullType = hullType;
}
public override void GetFromInput()
{
base.GetFromInput();
Console.Write("Enter the length of the boat: ");
Length = int.Parse(Console.ReadLine());
Console.Write("Enter the hull type for the boat: ");
HullType = Console.ReadLine();
}
public override string ToString()
{
return base.ToString() + string.Format("This vehicle is a boat with length of {0} and hull type of {1}.", Length, HullType);
}
}
Fleet.cs
using System;
class Fleet
{
static void Main(string[] args)
{
Vehicle v1 = new Vehicle();
v1.GetFromInput();
Console.WriteLine(v1);
//... for the other vehicles
}
}

This can be achieved using class inheritance.
Each of your vehicle classes, need to inherit a common class that implements functionality need by 'all' vehicles, This class (Vehicle receptively), can then be used in C# to identify any type of vehicle class/type.
Instead of having a several classes where each class is solely responsible for a type of vechile, you can abstract out common functionality needed by each vehicle, and implement a class that exposes these common relationships:
using System;
public namespace CodeSpace {
public class Vehicle {
public Vehicle(Type type, string make, string model) {
Model = model;
Make = make;
Type = type;
}
public Type VehicleType { get; private set; }
public string Make { get; set; }
public string Model { get; set; }
}
public class Airplane : Vehicle {
public class Airplane(string make, string model) : base(typeof(Airplane), make, model) {
}
}
public class Boat : Vehicle {
public class Boat(string make, string model) : base(typeof(Boat), make, model) {
}
}
public class Car : Vehicle {
public class Car(string make, string model) : base(typeof(Car), make, model) {
}
}
class Program {
public static void Main(params string[] args ) {
var vehicles = new List<Vehicle>() {
new Boat("Canoe", "X2") as Vehicle,
new Boat("Raft", "A") as Vehicle,
new Car("Ford", "T") as Vehicle,
new Airplane("BMW", "Idk") as Vehicle,
};
foreach(var v in vehicles) {
Console.WriteLine(v.VehicleType.FullName);
}
}
}
}
Now all of your vehicles can be identified using one class that exposes all vehicles through a common interface.

Related

Factory Design Pattern implementation in console application

I am new to programming and learning through online stuff and you guys, nowadays! I am reading about Factory Design Pattern and tried to implement in the very basic project, I have a solution that has two projects one projects contain interfaces, and the other contains implementation, I have read about factories but unfortunately, I have no idea how to implement in my project, In one project, I have 2 interfaces IBasicCars and ILuxuryCars, IluxuryCars implementing IBasicCars and then in the second project I have a class that inherits from ILuxuryCars and implement all of its methods and IBasicCars methods and properties, here is my code for that class.
public class LuxuryCars : ILuxuryCar
{
private string _color { get; set; }
public string Color
{
get
{
return _color;
}
set
{
_color = value;
}
}
private int _model { get; set; }
public int Model
{
get
{
return _model;
}
set
{
_model = value;
}
}
private string _make { get; set; }
public string Make
{
get
{
return _make;
}
set
{
_make = value;
}
}
public void Break()
{
Console.WriteLine("This is the basic function of all cars !!!");
}
public void CruiseControl()
{
Console.WriteLine("This is the luxury feature for luxury cars !!!");
}
public void Drive()
{
Console.WriteLine("This is the basic function of all cars !!!");
}
public void Navigation()
{
Console.WriteLine("This is the luxury feature for luxury cars !!!");
}
public void Park()
{
Console.WriteLine("This is the basic function of all cars !!!");
}
}
now I have another class "FactoryObject" in that project that has nothing in it right now, can someone please tell me to do I implement the factory design pattern?
that is how I am calling these methods in main method
static void Main(string[] args)
{
ILuxuryCar lc = new LuxuryCars();
lc.Color = "Black";
lc.Make = "Honda";
lc.Model = 2007;
Console.WriteLine("Car color is: {0} Made by: {1} Model is: {2}", lc.Color, lc.Make, lc.Model);
lc.Navigation();
lc.CruiseControl();
lc.Break();
lc.Drive();
lc.Park();
Console.WriteLine();
IBasicCar b = new LuxuryCars();
b.Color = "Red";
b.Make = "Alto";
b.Model = 2019;
Console.WriteLine("Car color is: {0} Made by: {1} Model is: {2}", lc.Color, lc.Make, lc.Model);
lc.Break();
lc.Drive();
lc.Park();
Console.ReadLine();
}
A very simple factory could be
public interface ICarFactory{
ICar Create();
}
public class BasicCarFactory : ICarFactory{
public ICar Create() => new BasicCar();
}
public class LuxuryCarFactory : ICarFactory{
public ICar Create() => new LuxuryCar();
}
This makes it more complicated to create a car, but the important bit is that components that need to create new car objects can do so without knowing what kind of car is created.
You might for example check the license at startup, and depending on the license create different factories that you hand of to all the other components. This way you have the license check at one single place, instead of spread out over different components.
In simple cases you might not need a separate inteface, a Func<ICar> might be sufficient.

GetSet in C# not being parsed

Relatively minor question about something I am missing here,
I am attempting to do a simple GetSet in C# to get the hang of the syntax but appear to have missed something as all that is printed is GetSet.Role and not the actual attributes being assigned.
Have I just worded something wrong? Apologies for the minor question but any help is appreciated.
namespace GetSet
{
class Program
{
static void Main(string[] args)
{
Role Mage = new Role("Staff", "Robes", "Magic affinity");
Role Warrior = new Role("Sword", "Platebody", "Strength");
Role Rogue = new Role("Needle", "Leather", "Cunning");
Console.WriteLine(Mage);
Console.WriteLine(Warrior);
Console.WriteLine(Rogue);
//stop the program from closing
Console.ReadLine();
}
}
}
and the following is my class:
namespace GetSet
{
class Role
{
//private variables
private string weapon;
private string armour;
private string passive;
//public structs
public Role(string aWeapon, string aArmour, string aPassive)
{
weapon = aWeapon;
armour = aArmour;
passive = aPassive;
}
//Getters and Setters for above private variables
public string Weapon
{
get { return weapon; }
set { weapon = value;}
}
public string Armour
{
get { return armour; }
set { armour = value;}
}
public string Passive
{
get { return passive; }
set { passive = value;}
}
}
}
Add a ToString() to your Role class and set it return whatever you want:
public override string ToString()
{
return $"Weapon: {weapon}, Armor: {armor}, Passive: {passive}";
}
You need to override the ToString method on the GetSet class.
Something like:
public override string ToString()
{
return $"{weapon}/{armour}/{passive}";
}
Update
You can simplyfy your Role class.
internal class Role
{
public Role(string weapon, string armour, string passive)
{
Weapon = weapon;
Armour = armour;
Passive = passive;
}
public string Weapon { get; }
public string Armour { get; }
public string Passive { get; }
public override string ToString()
{
return $"{Weapon}/{Armour}/{Passive}";
}
}
Re: vasily.sib's comment.
If you need to change the properties after object creation then simply change
public string Passive { get; }
to
public string Passive { get; set; }
As other answers lacks of getters/setters syntax examples, I will post my.
namespace GetSet
{
public class Role
{
// private backing field
private string _weapon;
// properties can have getters and setters, that contains some logic
public string Weapon
{
get { return _weapon; }
set { if (_weapon != vale) _weapon = value; }
}
// there is an auto-getters/setters
// in this case, backing field is handled by .Net CLR
public string Armour { get; set; }
// getters and setters may have different access level
// also, note property initializer '= "John";' - this will set property value
// to "John" right before constructor invocation
public string Name { get; private set; } = "John";
// properties also can be readonly, so they can be setted only in constructors
public string Passive { get; }
// public constructor
public Role(string passive)
{
Passive = passive;
}
public void ChangeName(string newName)
{
Name = newName; // setting property through private setter
}
// I believe, that this method shouldn't be used to represent object as string
// At least, I think, you should never relay on it's return value, BUT it ups to you
public overide string ToString() => Name;
}
}
Also, as you can see, I'm not setting publicly available properties (properties with public setters, Weapon and Armour) in consturctors, because I can initialize them along with constructing Role object, like this:
var mage = new Role("Magic affinity") { Weapon = "Staff", Armor = "Robes" };
mage.ChangeName("John, Doe");
As said before, I beleive that it is not relay on object itself, how it will look in string. I thinking so, because if you for some reasons need to represent same object as different strings in different places of your code - this will cause troubles. So instead of this:
// this will call .ToString() method
Console.WriteLine(mage);
// output: John, Doe
I suggest this:
// represent object as you need
Console.WriteLine($"{mage.Name} - walks in {mage.Armour}, beats with {mage.Weapon}");
// output: John, Doe - walks in Robes, beats with Staff

Method overrides and polymorphysm

I am trying to create a program that allows the user to check into a hotel room. The program should check if the room is free and then allocate one of the free rooms if any are available. I have multiple rooms types such as a single room, a double room, a twin room and so on which all need to inherit from the base class Room.
Here is my code currently.
public class Room
{
public static bool[] av = { false, true, false };
public bool availability()
{
bool a = false;
foreach (var roomAv in av)
{
a = a || roomAv;
}
return a;
}
public bool availability(int room)
{
return av[room];
}
public int allocate()
{
if (availability())
{
int room = 0;
while (!av[room])
{
room++;
}
av[room] = false;
return room;
}
else
{
return -1;
}
}
public static void roomStatus()
{
for (int i = 0; i < av.Length - 1; i++)
{
Console.WriteLine(i + av[i].ToString());
}
}
}
class SingleRoom
{
}
The functions I have defined in the room class need to be usable by all the different room types but each hold their own separate array stating whether they are available or not. How can I do this? How can I access those functions for each class but on there own separate array instead of performing them just on the 'av' array like I have currently.
As you said you are new to C#, I would suggest to rethink on structure. You are in object-oriented paradigm. What you are thinking is plain old C-function oriented programming.
public class Room
{
public bool IsAvailable {get; set;}
public RoomType RoomType {get; set;}
public int RoomNo {get; set;}
public int Floor {get; set;}
public string RoomName {get; set;}
}
public enum RoomType
{
Single,
Double,
Twin,
King,
HoneymoonSuite
}
public class RoomManager
{
public List<Room> AllRooms {get; set;}
public RoomManager()
{
AllRooms = new List<Room>();
AllRooms.Add(new Room(){ RoomType=RoomType.Single,
RoomNo=1,
Floor=1,
RoomName="A101",
IsAvailable=true});
AllRooms.Add(new Room(){ RoomType=RoomType.Double,
RoomNo=2,
Floor=1,
RoomName="A102",
IsAvailable=false});
AllRooms.Add(new Room(){ RoomType=RoomType.HoneyMoonSuite,
RoomNo=1,
Floor=2,
RoomName="A201",
IsAvailable=true});
}
public bool IsAvailable(int roomNo)
{
//You need to check if roomNo is a valid RoomNo
return AllRooms.Any(r=>r.RoomNo==roomNo && r.IsAvailable);
}
public bool IsAvailable(string roomName)
{
//You need to check if roomName is valid RoomName
return AllRooms.Any(r=>r.RoomName==roomName && r.IsAvailable);
}
}
The functions i have defined in the room class need to be usable by
all the different room types but each hold their own separate array
stating whether they are available or not. how can i do this?
When you use the static keyword for a variable, you're saying the variable belongs to the type itself instead of the object instance. Quoting from MSDN Docs:
Use the static modifier to declare a static member, which belongs to
the type itself rather than to a specific object.
In other words, your array is "owned" by the class Room, not by individual objects of type Room created with new. If you want each object instance to own its own private member variables, then the static keyword needs to be removed. I.e.
public static bool[] av = { false, true, false };
should be:
public bool[] av = { false, true, false };
Note that the same applies to method names, i.e., if you use the static keyword on a method, the method is "owned" by the class/type itself, and not the individual object instances. This means, your roomStatus method must be used as Room.roomStatus() and trying new Room().roomStatus() would not be possible.
I'd actually recommend that you remove the array and turn this into a property, so that you can simply do something like:
Room r = new SingleRoom();
if(r.IsAvailable)
{
// ...
}
You should also refactor your code to follow .NET naming conventions for your methods, variable names, and make better use of object-orientation. I think Niraj Doshi's post is a good step in that direction.
Since you're new to C#, I'd recommend you get a hold of the book Effective C# by B. Wagner.
Update - Refactored Code
This is my take on refactoring the code, having a RoomManager, a IRoom interface, an abstract implementation of the IRoom interface called Room with code and functionality common to all rooms, a concrete SingleRoom for a more specific type, and a TextView class to manage how the data will be presented/displayed to the user (i.e. text-based output).
Notice that this following the Model-View-Controller (MVC) design pattern, with the Room classes being the models (i.e. data), the TextView being responsible for displaying the data (i.e. presentation), and the Main program itself being the controller (i.e. coordinating the other two).
Main Program
The program simply adds some rooms and then displays information for each of them, based on the manager's capacity.
using System;
using System.Collections.Generic;
namespace HotelRoomManager
{
class MainClass
{
public static void Main (string[] args)
{
RoomManager mgr = new RoomManager (5);
for (uint i = 0; i < mgr.Capacity; ++i)
mgr.AddRoom (new SingleRoom (1, i + 1) );
List<IRoom> rooms = mgr.GetAllRooms ();
TextView view = new TextView ();
view.RenderHeader ();
view.RenderModels (rooms);
mgr.RemoveAllRooms ();
}
}
}
IRoom Interface
The interface defines a type and is the basis for all the rooms. Interfaces are used to define contracts with clients, and does not rely on implementation details, which makes it a good object-oriented practice.
using System;
namespace HotelRoomManager
{
public enum BedType
{
Single,
Double,
Twin,
Queen,
King
}
public interface IRoom
{
BedType BedType { get; }
uint Floor { get; }
uint Number { get; }
bool IsOccupied { get; set; }
}
}
Abstract Room
The room simply contains code that is common to all rooms, regardless of their own individual details.
using System;
namespace HotelRoomManager
{
public abstract class Room : IRoom
{
private uint floor;
private uint number;
private bool occupied;
public Room (uint floor, uint number)
{
this.floor = floor;
this.number = number;
occupied = false;
}
public uint Floor {
get { return floor; }
}
public uint Number {
get { return number; }
}
public abstract BedType BedType { get; }
public bool IsOccupied {
get { return occupied; }
set { occupied = value; }
}
override public string ToString() {
return "Room(floor=" + floor + ", number=" + number + ")";
}
}
}
Concrete SingleRoom
By this point, this room only needs to report its actual type. It doesn't need to do anything special in addition to the common functionality already available.
using System;
namespace HotelRoomManager
{
public sealed class SingleRoom : Room
{
public SingleRoom (uint floor, uint number) : base(floor, number)
{}
override public BedType BedType {
get { return BedType.Single; }
}
}
}
The RoomManager
The manager simply helps to keep track of all the rooms and provides a simplified interface to interact with the collection.
using System;
using System.Collections.Generic;
namespace HotelRoomManager
{
public class RoomManager
{
private List<IRoom> rooms;
public RoomManager (uint capacity) {
rooms = new List<IRoom> ();
rooms.Capacity = (int) capacity;
}
public void AddRoom(IRoom room) {
rooms.Add (room);
}
public void RemoveRoom(IRoom room) {
rooms.Remove (room);
}
public List<IRoom> GetAllRooms() {
return rooms;
}
public void RemoveAllRooms() {
rooms.Clear ();
}
public uint Capacity {
get { return (uint) rooms.Capacity; }
}
}
}
The TextView
The sole responsibility of the view is to decide how the data from the models will be presented to the user. This decouples the data itself from how the data is displayed, making your system easier to maintain and expand. You can also have multiple views available instead of having to choose between one or the other.
using System;
using System.Collections.Generic;
using System.Text;
namespace HotelRoomManager
{
public class TextView
{
public TextView () {}
public void RenderHeader() {
Console.WriteLine ("Hotel Management System");
Console.WriteLine ("-----------------------");
}
public void RenderModels(List<IRoom> rooms) {
StringBuilder sb = new StringBuilder ();
foreach (IRoom r in rooms) {
sb.Append ("Floor : " + r.Floor + "\n");
sb.Append ("Number : " + r.Number + "\n");
sb.Append ("Bed : " + r.BedType + "\n");
sb.Append ("Occupied: " + (r.IsOccupied ? "Yes" : "No") + "\n\n");
}
Console.WriteLine (sb.ToString ());
}
}
}
Output
A quick run of the program will produce the following output:
Hotel Management System
-----------------------
Floor : 1
Number : 1
Bed : Single
Occupied: No
Floor : 1
Number : 2
Bed : Single
Occupied: No
Floor : 1
Number : 3
Bed : Single
Occupied: No
Floor : 1
Number : 4
Bed : Single
Occupied: No
Floor : 1
Number : 5
Bed : Single
Occupied: No
This is pretty simple, instead of a field, use a property:
public class Room
{
public virtual bool[] av { get; set; } = { false, true, false };
//All of your functions remain unchanged except you need to remove static
}
Then in your derived classes:
public class SingleRoom : Room
{
public override bool[] av { get; set; } = { true, true, false };
}
The inherited rooms will set the array which will be used in the base functions for availability so you only have to write it once.
This is another plus of properties over fields, where you can set a property such that it can be inherited. The only thing that was really "wrong" with your original code was that the array and some methods were declared static meaning that it was the same across all instances of the class. Availability should be an instance-level field/property, not a type-level one.
Your original code could work if you remove the static and made your derived classes like this:
public class SingleRoom
{
public SingleRoom
: base()
{
//Redefine the values of the array.
av = { true, true, false };
}
}
You put the array as static, meaning that all access to the array reaches the same object.
Remove that and each will have their own.
As per comments - the static identifier should be removed from the roomStatus method as well.

Too many calculated properties in my class

I have class which have too many related calculated properties.
I have currently kept all properties are read only.
some properties need long calculation and it is called again when its related properties are needed.
How can create this complex object .Also i want these properties should not be set from external code. I need show hide as i am binding properties for UI. Also i think order is also important.
My Class is something like
public string A
{
get
{
return complexMethod();
;
}
}
public string B
{
get
{
if (A == "value")
return "A";
else return "B";
;
}
}
public bool ShowHideA
{
get
{
return string.IsNullOrEmpty(A);
;
}
}
public bool ShowHideB
{
get
{
return string.IsNullOrEmpty(B);
;
}
}
public string complexMethod()
{
string value = "";
// calculation goes here
return value;
}
}
Thanks
You need to use Lazy type provided by .net:
Lazy<YourType> lazy = new Lazy<YourType>();
Make your properties internal to not be set from external code.
Well tall order isn't it?
One of the coolest things about extension methods is you can use types. This is perfect for writing external programs to calculate property values. Start like this...
public static class XMLibrary
{
public static MC CalculateValues(this MC myclass)
{
//for each property calculate the values here
if (myclass.Name == string.Empty) myclass.Name = "You must supply a name";
if (myclass.Next == 0) myclass.Next = 1;
//when done return the type
return myclass;
}
}
public class MC
{
public string Name { get; set; }
public int Next { get; set; }
}
public class SomeMainClass
{
public SomeMainClass()
{
var mc = new MC { Name = "test", Next = 0 };
var results = mc.CalculateValues();
}
}
There are many other ways to do class validation on a model, for example dataannotations comes to mind, or IValidatableObject works too. Keeping the validation separate from the class is a good idea.
//Complex properites are simple
public class MyComplextClass{
public List<MyThings> MyThings {get;set;}
public List<FileInfo> MyFiles {get;set;}
public List<DateTime> MyDates {get;set;}
}

What pattern should I use to express a Hierarchical Enum?

I'm experimenting with an API for publishing values at a given time (tuples of value and time). These samples will be used by a data viewer (e.g. a graph).
I want to associate the value with a Quantity and a Unit, for example length in meters. That way my "viewer" can scale it appropriately.
I'm looking for a sort of hierarchical enum, like this:
enum Quantity
{
Mass.Kg,
Mass.g,
Length.m,
Length.mm
}
But this doesn't exist in C#.
I'm not sure the best pattern to express this and I've come up with the following. Is there a recognised, or better way to do this?
using System;
using Moq;
namespace ConsoleApplication26
{
class Program
{
static void Main(string[] args)
{
//use a Mock to play with the API
Mock<ITelemetryPublisherFactory> mockTelemetryPublisherFactory = new Mock<ITelemetryPublisherFactory>();
var telemetryPublisherFactory = mockTelemetryPublisherFactory.Object;
//example usages
var massTelemetryPublisher = telemetryPublisherFactory.GetChannelSamplePublisher<Double>("My Mass", Mass.Kg);
massTelemetryPublisher.PublishChannelSampleAtTimeNow(83.4);
var lengthTelemetryPublisher = telemetryPublisherFactory.GetChannelSamplePublisher<Int32>("My Height", Length.μm);
lengthTelemetryPublisher.PublishChannelSampleAtTimeNow(1800000);
//10 years time..
lengthTelemetryPublisher.PublishChannelSampleAtTimeNow(1800000);
massTelemetryPublisher.PublishChannelSampleAtTimeNow(120.1);
}
}
public interface ITelemetryPublisherFactory
{
ITelemetryPublisher<T> GetChannelSamplePublisher<T>(String channelName, Quantity quantity);
}
public interface ITelemetryPublisher<T>
{
void PublishChannelSampleAtTimeNow(T sampleValue);
}
public abstract class Quantity {}
public class Mass : Quantity
{
private enum Unit
{
g,
Kg
}
private readonly Unit _unit;
private Mass(Unit unit)
{
_unit = unit;
}
public static Quantity Kg {get { return new Mass(Unit.Kg); }}
public static Quantity g { get { return new Mass(Unit.g); } }
public override string ToString()
{
return String.Format("Mass.{0}", _unit);
}
}
public class Length : Quantity
{
private enum Unit
{
m,
mm,
μm,
beardSecond
}
private readonly Unit _unit;
private Length(Unit unit)
{
_unit = unit;
}
public static Quantity m { get { return new Length(Unit.m); } }
public static Quantity mm { get { return new Length(Unit.mm); } }
public static Quantity μm { get { return new Length(Unit.μm); } }
public static Quantity beardSecond { get { return new Length(Unit.beardSecond); } }
public override string ToString()
{
return String.Format("Length.{0}", _unit);
}
}
}
I think it's better to create a Unit class for the unit of measure and a Quantity class that associates a unit of measure with an amount. Look at the Quantity pattern for the idea. Since you also want to record the "type" of the unit of measure, you could create a UnitType class that records that information:
public sealed partial class UnitType {
public string Name { get; private set; }
public UnitType(string name) {
Name = name;
}
}
public sealed partial class Unit {
public string Name { get; private set; }
public UnitType Type { get; private set; }
public Unit(string name, UnitType type) {
Name = name;
Type = type;
}
}
(You should make them proper value types by overriding Equals and GetHashCode)
The Unit class can be extended to provide for e.g. conversions, compound units, formatting and parsing.
Then, you can define the common cases inside the classes:
public partial class UnitType {
public static readonly UnitType Mass = new UnitType("Mass");
public static readonly UnitType Length = new UnitType("Length");
}
public partial class Unit {
public static readonly Unit Grams = new Unit("g", UnitType.Mass);
public static readonly Unit Kilos = new Unit("kg", UnitType.Mass);
// ...
}
Or define your "hierarchies" with static classes:
public static class Mass {
public static readonly UnitType Type = new UnitType("Mass");
public static readonly Unit Grams = new Unit("g", Type);
public static readonly Unit Kilos = new Unit("kg", Type);
...
}
public static class Length ...
The Quantity class would also be an immutable value type (just showing its usage):
var eniacWeight = new Quantity(27, Mass.Tons);
Or you could use extension methods to create Quantitys:
var eniacWeight = 27.Tons();
(from ENIAC)
This is not possible. Enums are primitive types and cannot inherit from other enums, as inheritance is a property of objects.
Hierarchical enum isn't possible, as noted above. If you're exclusively using metric, though, you can utilise standard prefixes if it helps.
enum MeasurementUnits
{
Gram,
Metre,
Litre,
Hectare
// etc
}
enum MeasurementPrefix
{
Milli,
Natural,
Kilo,
Mega
// etc
}
This may not be precisely what you want, but it will provide the type of 'grouping' that you might be looking for (e.g. group measurements that are about length, weight etc by checking their 'units' value).
Your suggested approach seems reasonable to me, and I use something similar in a project of mine. However, I keep the actual value part of the object, and I use struct instead of class, since they are naturally value types. Inheritance is not necessary here (and not possible with structs, anyways), so I use an interface to create a contract and act as a constraint when needed (I called it IUnitOfMeasure).
I do not recommend creating one enum with all the units of the various types of measurement combined; it is hell validating the unit to make sure someone didn't reference a Mass unit when working with Length.
public interface IUnitOfMeasure<TThis>
where TThis : IUnitOfMeasure<TThis>
{
TThis ConvertTo(TThis value);
}
public struct Mass : IUnitOfMeasure<Mass>
{
public enum Units
{
Gram,
Kilogram
}
private double _value;
private Mass.Units _unit;
public double Value { get { return _value; } }
public Mass.Units Unit { get { return _unit; } }
public Mass(double value, Mass.Units unit)
{
_value = value;
_unit = unit;
}
public Mass ConvertTo(Mass value)
{
switch(value.Unit)
{
case Units.Gram:
return new Mass(Unit == Units.Gram ? Value : Value/1000, Units.Gram);
case Units.Kilogram:
return new Mass(Unit == Units.Gram ? Value*1000 : Value, Units.Kilogram);
default:
throw new NotImplementedException();
}
}
public override string ToString()
{
return string.Format("{0} {1}", Value, Unit);
}
public static readonly Mass G = new Mass(0, Units.Gram);
public static readonly Mass Kg = new Mass(0, Units.Kilogram);
}
Usage:
var kg = new Mass(5.0, Mass.Units.Kilogram);
Console.WriteLine(kg); // writes "5 Kilogram"
var g = kg.ConvertTo(Mass.G);
Console.WriteLine(g); // writes ".005 Gram"
If you don't care about keeping the value, and just want to keep enum/static values in a central place:
public static class UnitOfMeasure
{
public enum Mass
{
Gram,
Kilogram
}
public enum Length
{
Meter,
Kilometer
}
// etc.
}
Usage: var unit = UnitOfMeasure.Mass.Kilogram;
You cannot introduce inheritance with enums. Enums are just a convenience mechanism to allow you to use meaningful textual identifiers in your code. From The code you have, I suggest you either use an enum like;
public enum UnitOfMeasure
{
MassGrams,
MassKg,
LengthMM,
LengthCM,
. . .
}
Or split it out to where it's appropriate, so that Mass and Length are defined separately for example.
The 'inheritance' is just something you've introduced in your thinking about this problem, but it isn't necessary to your solution. When you want to deal with Mass, you only look at the flags/enums appropriate to mass.

Categories

Resources