Selecting a random object from a list of objects - c#

I'm trying to randomly select one of the customer items from the list. I am not sure what to do to actually print out the info within the list.
I have this as my customer class
namespace PizzaParlor
{
class Customer
{
private string name;
private int flavor;
private int price;
private int quality;
private int speed;
private int accessibility;
private int brand;
private int convenience;
private int variety;
public Customer(string name, int flavor, int price, int quality, int speed, int accessibility, int brand, int convenience, int variety)
{
this.name = name;
this.flavor = flavor;
this.price = price;
this.quality = quality;
this.speed = speed;
this.accessibility = accessibility;
this.brand = brand;
this.convenience = convenience;
this.variety = variety;
}
// Name, Speed, Quality, Variety, Convenience, Accessibility, price, brand, flavor
public string Name
{
get { return name; }
set { name = value; }
}
public int Speed
{
get { return speed; }
set { speed = value; }
}
public int Quality
{
get { return quality; }
set { quality = value; }
}
public int Variety
{
get { return variety; }
set { variety = value; }
}
public int Convenience
{
get { return convenience; }
set { convenience = value; }
}
public int Accessibility
{
get { return accessibility; }
set { accessibility = value; }
}
public int Price
{
get { return price; }
set { price = value; }
}
public int Brand
{
get { return brand; }
set { brand = value; }
}
public int Flavor
{
get { return flavor; }
set { flavor = value; }
}
}
}
and this as my main class that I set up to work with the customer class:
namespace PizzaParlor
{
class Program
{
static void Main(string[] args)
{
var random = new Random();
List<Customer> CustomerList = new List<Customer>();
CustomerList.Add(new Customer("bill", 20,15,10,5,10,20,5,15));
CustomerList.Add(new Customer("kevin", 15, 10, 5, 20, 15, 15, 0, 20));
CustomerList.Add(new Customer("clair", 8,25,2,25,5,15,0,20));
CustomerList.Add(new Customer("jim", 15,20,10,15,0,40,0,0));
CustomerList.Add(new Customer("rachel", 20,15,10,5,10,30,0,10));
CustomerList.Add(new Customer("jeff", 30,20,5,5,10,10,0,20));
CustomerList.Add(new Customer("Mike", 21,23,0,10,14,16,0,16));
CustomerList.Add(new Customer("john", 25,15,10,10,10,5,5,20));
int index = random.Next(CustomerList.Count);
Console.WriteLine(CustomerList[index]);
}
}
}
I know that the random.Next(CustomerList.Count) will randomly a select from the list but I don't know why it is returning this output:

This is because the when you attempt to print an object (e.g. Customer, the default implementation of ToString() is executed. This produces the output that you see.
There are 2 ways of fixing it
Print explicit fields you're interested in
int index = random.Next(CustomerList.Count);
var customer = CustomerList[index];
Console.WriteLine($"customer name = {customer.Name}, flavour = {customer.Flavour}}");
Override the ToString implementation
class Customer
{
//...
// Existing code
// ..
public override string ToString ()
{
return $"customer name = {customer.Name}, flavour = {customer.Flavour}}";
}
}
In your main method
int index = random.Next(CustomerList.Count);
var customer = CustomerList[index];
Console.WriteLine(customer);

You can use Reflection to achieve this.
foreach (var prop in typeof(Customer).GetProperties())
{
Console.WriteLine("{0}={1}", prop.Name, prop.GetValue(CustomerList[index]));
}

Related

how do you add get and set for an array in c#

I'm coding a func that inputs an array with different year of birth and prints out the oldest person.
I'm trying to add a validation with get and set but my syntax is wrong.
enter image description here
TL;DR
Properties declaration part:
public class Employee
{
private string _fullName;
private int _yearIn;
public string FullName
{
get => _fullName;
set
{
if (!string.IsNullOrEmpty(value))
{
_fullName = value;
}
}
}
public int YearIn
{
get => _yearIn;
set
{
if (value > 0 && value <= 2020)
{
_yearIn = YearIn;
}
}
}
}
And a usage:
var employees = new List<Employee>();
for (int i = 0; i < 3; i++)
{
Console.WriteLine("Enter Name:");
string name = Console.ReadLine();
Console.WriteLine("Enter Year:");
int yearIn = Convert.ToInt32(Console.ReadLine());
employees.Add(new Employee
{
FullName = name,
YearIn = yearIn
});
}
Update
You can do the same in a bit different manner though:
public class Employee
{
private string _fullName;
private int _yearIn;
public bool IsNameValid { get; set; }
public bool IsYearValid { get; set; }
public string FullName
{
get => _fullName;
set
{
_fullName = value;
IsNameValid = string.IsNullOrEmpty(value);
}
}
public int YearIn
{
get => _yearIn;
set
{
_yearIn = value;
IsYearValid = (value < 0) || (value > 2020);
}
}
}
And later:
Console.WriteLine($"Employee name is: {employees[i].IsNameValid}");
Console.WriteLine($"Employee year is: {employees[i].IsYearValid}");
Update 2
And the last alternative version is that you can use Validation attributes:
public class Employee
{
[Required]
[Range(0, 2020)]
public int YearIn { get; set; }
[Required]
[StringLength(50)]
public string FullName { get; set; }
}
later:
var empl = new Employee{ YearIn = yearIn, FullName = name};
var context = new ValidationContext(empl, serviceProvider: null, items: null);
var results = new List<ValidationResult>();
var isValid = Validator.TryValidateObject(empl, context, results, true);
Console.WriteLine($"Is model valid: {isValid}");
if (isValid)
{
employees.Add(new Employee
{
FullName = name,
YearIn = yearIn
});
}
You can create wrapper classes over array and use indexer method for accessing the array item.
There in, you can put all your validation logic.
class IntData
{
public IntData(int size)
{
data = new int[size];
}
// Array of temperature values
private int[] data;
public int this[int index]
{
get
{
return data[index];
}
set
{
// Do your validation here
if (value < 5000)
{
data[index] = value;
}
}
}
}
static void Main(string[] args)
{
IntData year = new IntData(3);
year[0] = 2000;
year[1] = 6000; // This value won't set because of validation
year[2] = 4000;
Console.Read();
}

Where is the 'value' variable set in properties?

In C# properties, where is the 'value' variable defined? I can see it used in the bodies of setters before it is defined anywhere.
namespace TestBindings
{
public class Dog
{
private decimal age;
private string name;
private const int AgeFactor = 7;
public Dog(decimal age, string name)
{
this.age = age;
this.name = name;
}
public decimal AgeDogYears
{
get { return age / AgeFactor; }
set { age = value * AgeFactor; }
}
public decimal AgeHumanYears
{
get { return age; }
set { age = value; } //here
}
public string Name
{
get { return name; }
set { name = value; } // and here
}
}
}
The 'value' variable is automatically passed in from the use-site and is a pre-defined variable name for the value passed in the set expression.
e.g.
var jack = new Dog(13, "jack");
jack.Name = "Jackson";
Here the value after the = sign is being passed into the setter defined in the class as 'value'.
public string Name
{
get { return name; }
set { name = value; } //here
}
It's roughly equivalent to the Java expression it replaces of having an explicit getter and setter method, just using different syntax in order to unify settings fields and properties.
e.g.
public class Dog {
private double age;
private String name;
private final int AgeFactor = 7;
public Dog(double age, String name) {
this.age = age;
this.name = name;
}
public double getAgeHumanYears() {
return age;
}
public void setAgeHumanYears(double value) {
this.age = value;
}
public double getAgeDogYears() {
return age / AgeFactor;
}
public void setAgeDogYears(double value) {
age = value * AgeFactor;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
With our test changing to.
private Dog jack = new Dog(13, "jack");
jack.setName("Jackson");

Should a class have string fields for values from SQL JOIN from dictionary tables

I have a class (code below) that I use to save to and read from db. Everything works fine but when it comes to finally print some object information taken from dictionary tables I really don't know where to put them. (Active Record).
Code of class:
class Object
{
public int id;
public int size;
public int color;
public int author;
public Object(int id, int size, int color, int author)
{
this.id = id;
this.size = size;
this.color = color;
this.author = author;
}
// add, update, delete methods
}
So for above class the SQL:
select id, size, color, author from object;
Should I add string fields into this class to look like this:
class Object
{
public int id;
public int size;
public int color;
public int author;
// String fields for dictionary
public string sizeString;
public string colorString;
public string authorString;
//
// Nr 1
public Object(int id, int size, int color, int author)
{
this.id = id;
this.size = size;
this.color = color;
this.author = author;
}
// Nr 2
public Object(int id, string size, string color, string author)
{
this.id = id;
this.size = sizeString;
this.color = colorString;
this.author = authorString;
}
// add, update, delete methods
}
SQL:
select o.id, s.size, c.color, a.name
from object o
join sizes s on o.size = s.id
join colors c on o.color = c.id
join authors a on o.author = a.id
If this approach is correct then should my new constructor (Nr 2) look like above I mean should I left the int fields empty or always get all data from db:
public Object(int id, int size, int color, int author,
string sizeString, string colorString,
string authorString)
{
this.id = id;
this.size = size;
this.color = color;
this.author = author;
this.sizeString = sizeString;
this.colorString = colorString;
this.authorString = authorString;
}
SQL:
select o.id, o.size, o.color, o.author,
s.size as sizeS, c.color as colorS, a.name as authorS
from object o
join sizes s on o.size = s.id
join colors c on o.color = c.id
join authors a on o.author = a.id
If whole idea of adding addtional string fields is bad please steer me in a right direction. Thanks for help.
You can put in items which resolve the ids to their corresponding values such as below:
using System;
using System.Collections.Generic;
namespace StackOverflow
{
class Program
{
static void Main(string[] args)
{
IColorResolver colors = new ColorResolver();
IObject demoObject1 = new Object(1, 1, 1, 1, colors);
IObject demoObject2 = new Object(2, 3, 3, 3, colors);
Console.WriteLine("demoObject1: {0}", demoObject1.Color.Name);
Console.WriteLine("demoObject2: {0}", demoObject2.Color.Name);
Console.ReadKey();
}
}
public interface IObject
{
int Id { get; }
ISize Size { get; set; }
IColor Color { get; set; }
IAuthor Author { get; set; }
}
public class Object: IObject
{
bool isDirty = false;
readonly int id;
int size;
int color;
int author;
IColorResolver colors;
public int Id { get { return this.id; } }
public ISize Size { get; set; } //this would implement code like Color's
public IAuthor Author { get; set; }//this would implement code like Color's
public IColor Color
{
get { return colors.GetColor(color); }
set
{
if (!this.color.Equals(value.Id))
{
this.color = value.Id;
this.isDirty = true;
}
}
}
public Object(int id, int size, int color, int author, IColorResolver colorResolver)
{
this.id = id;
this.size = size;
this.color = color;
this.author = author;
this.colors = colorResolver;
}
// add, update, delete methods
}
public interface ILookupValue
{
int Id { get; }
string Name { get; /*set;*/ } //no set since this is a lookup so we don't want to amend it
}
public interface IColor: ILookupValue
{
IColorResolver GetResolver();
}
public interface IAuthor : ILookupValue { /* ... */ }
public interface ISize : ILookupValue { /* ... */ }
public class Color : IColor
{
int id;
string name;
IColorResolver colors;
public int Id { get { return this.id; } }
public string Name { get { return this.name; } }
public Color(int id, string name, IColorResolver colors)
{
this.id = id;
this.name = name;
this.colors = colors;
this.colors.AddColor(this);
}
public IColorResolver GetResolver() { return this.colors; }
}
public interface IColorResolver
{
IColor GetColor(int id);
void AddColor(IColor color);
}
public class ColorResolver : IColorResolver
{
IDictionary<int, IColor> colors = new Dictionary<int, IColor>();
public ColorResolver()
{
/*
in reality you'd probably pass a data layer object through
the constructor to fetch these values from your database
*/
new Color(1, "Red", this);
new Color(2, "Green", this);
new Color(3, "Blue", this);
}
public void AddColor(IColor color)
{
this.colors.Add(color.Id, color);
}
public IColor GetColor(int id)
{
IColor result;
this.colors.TryGetValue(id, out result); //you could throw an exception here if not found
return result;
}
}
}
The reason for the huge amount of interfaces in the above code is this makes testing simpler; i.e. I can create Mock objects for any of my objects and pass them in instead of my real objects.

Dapper.NET filling a class in "list of class"

I am new on Dapper.NET kinda stuck on this. I am trying to fill a class which has another class from multirow result set.
# DATABASE SP >
SELECT b.BuildingId, b.BuildingName, b.Wood, b.Food, b.Stone, b.Gold FROM UserBuildings ub, Buildings b WHERE b.BuildingId = ub.BuildingId AND UserId = #UserId
# CODE >
using (IDbConnection connection = OpenConnection())
{
List<Building.Building> buildings = new List<Building.Building>();
var multi = connection.QueryMultiple<Building.Building, Resource.Resource>("UserBuildingGet", new { UserId = UserId }, commandType: CommandType.StoredProcedure).ToList();
building.Resource = multi.Read<Resource.Resource>().Single();
return building;
}
# CLASSES >
public class Building
{
private int _BuildingId;
private string _BuildingName;
private Resource.Resource _Resource;
public int BuildingId
{
get { return _BuildingId; }
set { _BuildingId = value; }
}
public string BuildingName
{
get { return _BuildingName; }
set { _BuildingName = value; }
}
public Resource.Resource Resource
{
get { return _Resource; }
set { _Resource = value; }
}
public Building(int BuildingId, string BuildingName, Resource.Resource Resource)
{
this.BuildingId = BuildingId;
this.BuildingName = BuildingName;
this.Resource = Resource;
}
}
public class Resource
{
private int _Wood;
private int _Food;
private int _Stone;
private int _Gold;
public int Wood
{
get { return _Wood; }
set { _Wood = value; }
}
public int Food
{
get { return _Food; }
set { _Food = value; }
}
public int Stone
{
get { return _Stone; }
set { _Stone = value; }
}
public int Gold
{
get { return _Gold; }
set { _Gold = value; }
}
public Resource(int Wood, int Food, int Stone, int Gold)
{
this.Wood = Wood;
this.Food = Food;
this.Stone = Stone;
this.Gold = Gold;
}
}
Your code needs to define what separates the data. Use the splitOn parameter of GridReader.Read
var buildings = new List<Building.Building>();
using (IDbConnection connection = OpenConnection())
{
using(var reader = connection.QueryMultiple("UserBuildingGet",
new { UserId = UserId },
commandType: CommandType.StoredProcedure))
{
var building = reader.Read<Building.Building,
Resource.Resource,
Building.Building>
((b, r) => { b.Resource = r; return b; }, splitOn: "Wood");
buildings.AddRange(building);
}
}
return buildings;
See: Is there a way of using MultiMapping and QueryMultiple together in Dapper?
Sample:
public class Building
{
public int BuildingId { get; set; }
public string BuildingName { get; set; }
public Resource Resource { get; set; }
public override string ToString()
{
return string.Format("Id: {0} Name: {1} Resource: {2}", BuildingId, BuildingName, Resource);
}
}
public class Resource
{
public int Wood { get; set; }
public int Food { get; set; }
public int Stone { get; set; }
public int Gold { get; set; }
public override string ToString()
{
return string.Format("Wood: {0} Food: {1} Stone {2} Gold {3}", Wood, Food, Stone, Gold);
}
}
var sql = #"SELECT 1 AS BuildingId, 'tower' AS BuildingName, 1 AS Wood, 1 AS Food, 1 AS Stone, 1 AS Gold
UNION ALL
SELECT 2 AS BuildingId, 'shed' AS BuildingName, 1 AS Wood, 1 AS Food, 1 AS Stone, 1 AS Gold";
var buildings = new List<Building>();
using(var connection = GetOpenConnection())
{
using(var reader = connection.QueryMultiple(sql))
{
var building = reader.Read<Building, Resource, Building>(
(b, r) => { b.Resource = r; return b; }, splitOn: "Wood");
buildings.AddRange(building);
}
}
foreach(var building in buildings)
{
Console.WriteLine(building);
}

'does not implement interface member 'System.ICloneable.Clone()'

I'm having a small issue calling in the Icloneable interface
I've told the class I want to use the interface as such:
class UnitClass: ICloneable
and have placed in a function for Cloning
public Object Clone()
{
return this.MemberwiseClone();
}
however for some reason the program is telling me that I have not implemented System.ICloneable.clone() I even tried giving the function the explicit name like so...
public Object System.ICloneable.Clone()
but with little effect, anybody know what I'm doing wrong?
edit: Full class
class UnitClass: ICloneable
{
//-----------------------------------------------------------------------------------------------
//----------------------------------------------Variables----------------------------------------
private int unitID; //added for xml
private string unitName;
private int unitBaseHP;
private int unitCurrentHP;
private Carrier unitCarrier;
private int unitRechargeTime;
private int turnLastPlayed;
private int strengthAgainstFighters;
private int strengthAgainstBombers;
private int strengthAgainstTurrets;
private int strengthAgainstCarriers;
//-----------------------------------------------------------------------------------------------
//---------------------------------------------Constructor---------------------------------------
public UnitClass()
{
unitID = 0;
unitName = "Name Not Set";
unitBaseHP = 0;
unitCurrentHP = 0;
unitCarrier = null;//Carrier works as faction ie red/blue or left/right
unitRechargeTime = 0;
turnLastPlayed = 0;
strengthAgainstFighters = 0;
strengthAgainstBombers = 0;
strengthAgainstTurrets = 0;
strengthAgainstCarriers = 0;
}
//-----------------------------------------------------------------------------------------------
//---------------------------------------------Gets and Sets-------------------------------------
public int UnitID//public
{
set { unitID = value; }
get { return unitID; }
}
public string UnitName//public
{
set { unitName = value; }
get { return unitName; }
}
public int UnitBaseHP//public
{
set { unitBaseHP = value; }
get { return unitBaseHP; }
}
public int UnitCurrentHP//public
{
set { unitCurrentHP = value; }
get { return unitCurrentHP; }
}
public Carrier UnitCarrier//public
{
set { unitCarrier = value; }
get { return unitCarrier; }
}
public int UnitRechargeTime//public
{
set { unitRechargeTime = value; }
get { return unitRechargeTime; }
}
public int TurnLastPlayed//public
{
set { turnLastPlayed = value; }
get { return turnLastPlayed; }
}
public int StrengthAgainstFighters//public
{
set { strengthAgainstFighters = value; }
get { return strengthAgainstFighters; }
}
public int StrengthAgainstBombers//public
{
set { strengthAgainstBombers = value; }
get { return strengthAgainstBombers; }
}
public int StrengthAgainstTurrets//public
{
set { strengthAgainstTurrets = value; }
get { return strengthAgainstTurrets; }
}
public int StrengthAgainstCarriers//public
{
set { strengthAgainstCarriers = value; }
get { return strengthAgainstCarriers; }
}
//---------------------------------------------------------------------------
public object Clone()
{
return this.MemberwiseClone();
}
}
This built fine for me.
public class MyClone : ICloneable
{
public object Clone()
{
return this.MemberwiseClone();
}
}
You don't perhaps want to share any more of your class? Nothing is really jumping out at me.

Categories

Resources