Create a class with array of objects - c#

Code below defines a ChargeCustomer class that contains an array of type "customers". I want to be able to create an object with either 1 "customer" or 2 "customers" based on the constructor parameters. Is this the right way to do so in C#:
public class ChargeCustomer
{
private Customer[] customers;
public ChargeCustomer( string aName, string bName, int charge )
{
customers = new Customer[2];
customers[0] = new Customer(aName, charge);
customers[1] = new Customer(bName, charge);
}
public ChargeCustomer( string bName, int charge )
{
customers = new Customer[1];
customers[0] = new Customer( bName, charge );
}
}
Thanks!

Note: This assumes that DropBox was a mis-paste in the original question.
You can move things around and have 1 constructor using params for any number of names, like this:
public class ChargeCustomer
{
private Customer[] customers;
public ChargeCustomer( int charge, params string[] names)
{
customers = new Customer[names.Length];
for(int i = 0; i < names.Length; i++) {
customers[i] = new Customer(names[i], charge);
}
}
}
Using this approach you just pass the charge first and any number of customer names, like this:
new ChargeCustomer(20, "Bill", "Joe", "Ned", "Ted", "Monkey");
It will create an array the correct size and fill it using the same charge for all, and 1 Customer per name by looping through the names passed in. All that being said, there's probably a much simpler overall solution to your problem, but without making changes outside the Customer class (aside from the constructor calls), this would be the simplest approach/smallest change.

Related

How to get the first value in Dictionary< string, int > #shorthand

Dictionary shoppingList = new Dictionary <string, int>()
{
{"Eggs",200 },
{"Milk",200},
{"Fish",400},
{"Apples",150}
};
Dictionary does not have a concept of "first", and indeed is free to re-order things. Now you can get a .First() item, but it's only guaranteed for that enumeration, and the order might not be the order you expect or want. That said, I'm not aware of a specific case .Net will actually do this; just be aware it's not part of the "contract" for the type.
Really, it seems like what you have here is more of a List<ShoppingItem> (it's even in the name of the variable!), where ShoppingItem is a class with properties for Name and Price.
To be more predictable about retrieving the first item, it might be helpful to create a class called ShoppingItem and then use a List instead of a Dictionary:
public class ShoppingItem
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}
Create a List using your new ShoppingItem type.
List<ShoppingItem> shoppingList = new List<ShoppingItem>();
Populate your list:
shoppingList.Add(
new ShoppingItem
{
Id = 1,
Name = "Eggs",
Price = 200
});
shoppingList.Add(
new ShoppingItem
{
Id = 2,
Name = "Applies",
Price = 150
});
Then, finding the first in the sequence can be achieved in a number of ways:
var firstUsingFirst = shoppingList.First();
var firstUsingIndex = shoppingList[0];
var firstLowestId = shoppingList.Find(item => item.Id == (shoppingList.Min(e => e.Id)));
Each method returns a ShoppingItem object, so get the values of the class properties like:
int firstId = firstUsingFirst.Id
Lots of examples in the documentation here.

C# Trouble managing Lists in classes

Good evening,
Just to have a little context, I started C# just a few months ago and I am making a bank application with C# as an assignment.
I have 2 classes: Customer and Bank Employee that inherit from the abstract class Person. The Account class (basically savings, current, whatever) inherits from the Customer class.
UML
I only kept the attributes because the rest doesn't matter for what's to follow.
My problem is that i can't seem to understand what I am doing wrong with the AllAccounts list regrouping all the Accounts from the Customer.
Here is the thing, i mostly manipulate the AllAccounts list inside the Customer class and as soon as it's out of whatever method it was, it doesn't save any changes.
I checked by displaying the length of the list inside the method and outside of it (let it be in program.cs or Customer.cs). By default, the method creates 2 accounts so the first number displayed is 2. However the second number displayed is 0 and this is where I am lost.
For example, I have this method public Customer CreateCustomer() that returns a Customer class, the first line i would write is AllAccounts = new List<Account>();. I later found out that it wasn't working, I then decided to initialise the list in a constructor.
public Customer()
{
AllAccounts = new List<Account>();
}
It was still not keeping whatever changes i made to the AllAccounts list.
My latest attempt was to initialise AllAccounts list inside the main, which gave me an null error when trying to display the length.
I'd like to understand What I am missing and where I am wrong.
Thanks for reading.
EDIT:
Here are my attributes for Customer, the constructor and the CreateCustomer method:
Customer.cs
private int pinNumber { get; set; }
private string accountNumber { get; set; }
public List<Account> AllAccounts { get; set; }
public Customer()
{
AllAccounts = new List<Account>();
}
public Customer CreateCustomer()
{
string full = "accountnumber"; // Just a login thing, dont mind
int pin = 1; // same here
string path = "Customers";
string saving = path + "\\saving.txt";
string current = path + "\\current.txt";
AllAccounts.Add(new Account() { path = saving, name = "saving", total = 0 });
AllAccounts.Add(new Account() { path = current, name = "current", total = 0 });
return new Customer() { firstName = firstName, lastName = lastName, pinNumber = pin, accountNumber = full };
}
Inside program.cs, that's how I call the createcustomer method:
var Client = new Customer();
//get client info
AllCustomers.Add(Client.CreateCustomer());
After adding my customer to* AllCustomers*, the firstname, lastname are saved but not what was on AllAccounts.
When i run this:
Console.WriteLine(AllCustomers[0].AllAccounts[0].name);
It displays null basically, not even an error is shown it's just a null character.
By the way thanks for your replies!
Well the Issue is when you are returning new Customer() in CreateCustomer(). You are not passing the list which was created by CreateCustomer().
return new Customer() { firstName = firstName, lastName = lastName, pinNumber = pin, accountNumber = full,AllAccounts=AllAccounts };
So, right now you create a new Account list but its basically not being assigned to the customer, hence no account to any customer and once you create a new Customer, because of the constructor initializing of the new Account List all the previous data is lost.
Update your return statement and it would work

Functional way to create and populate arrays in C#

How can I create and populate the array in a functional way than the following imperative way?
Imperative Code
IList<Customer> customers = new List<Customer>();
// my input data is array of strings
string[] ids = {"4", "6"};
string[] names = {"John Doe", "Jane Doe"};
for (var i = 0; i<ids.Length; i++)
{
customers.Add(new Customer
{
Id = Int32.Parse(ids[i]),
Name = names[i],
});
}
Customer class
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
}
Something like this?
customers = ids.Zip(names, (id, name) => new Customer { Id = Int32.Parse(id), Name = name }).ToList();
If by functional you mean without loops, you can use LINQ's Zip to combine values and produce an IEnmerable<Customer> :
var customers=ids.Zip(names,(id,name)=> new Customer
{
Id = Int32.Parse(ids[i]);
Name = names[i];
})
.ToArray();
//Or .ToList(); if a List<T> is preferable
I say if because creating the array still requires allocating an array and modifying it.It's actually more expensive thatn creating an array in advance because ToArray() doesn't know how big an array to create, so it may need to reallocate its internal buffers.
A more functional approach would be to consume the IEnumerable<Customer> produced by Zip. That sequence of customer objects can be consumed by any other LINQ operator or custom methods that expect an IEnumerable<T>.
A more performant version would create the array in advance and copy the values from the IEnumerable produced by zip :
var customers=new Customer[ids.Length];
var values=ids.Zip(names,(id,name)=> new Customer
{
Id = Int32.Parse(ids[i]);
Name = names[i];
});
var i=0;
foreach(var values)
{
customers[i++]=v;
}

Storing values in list<> and changing them

I have been trying to create a program that allows the user to edit things such as the supply of mp3 players which have a base value stored in the program:
public struct MP3_Players
{
public int ID { get; set; }
public string Make { get; set; }
public string Model { get; set; }
public int MBsize { get; set; }
public decimal Price { get; set; }
public int Supply { get; set; }
}
MP3_Players player1 = new MP3_Players
{
ID = 1,
Make = "GET Technologies .inc",
Model = "HF 410",
MBsize = 4096,
Price = 129.95m,
Supply = 500
};
MP3_Players player2 = new MP3_Players
{
ID = 2,
Make = "Microsoft",
Model = "SOFT1",
MBsize = 1028,
Price = 432.99m,
Supply = 500
};
MP3_Players player3 = new MP3_Players
{
ID = 3,
Make = "PEAR",
Model = "APPLE3",
MBsize = 2056,
Price = 130.00m,
Supply = 500
};
MP3_Players player4 = new MP3_Players
{
ID = 4,
Make = "logitech",
Model = "DEF0",
MBsize = 2056,
Price = 53.35m,
Supply = 500
};
MP3_Players player5 = new MP3_Players
{
ID = 5,
Make = "Sennheiser",
Model = "HEIS1",
MBsize = 2056,
Price = 399.95m,
Supply = 500
};
Now making a method with a list isn't really an issue, I imagine it goes as follows:
public static void mutate()
{
List<MP3_Players> PlayerList = new List<MP3_Players>;
Playerlist.Add(player1);
Playerlist.Add(player2);
Playerlist.Add(player3);
Playerlist.Add(player4);
Playerlist.Add(player5);
}
My first question is simply a matter of improvement of code, but I suppose many people reading this will understand the problems I'm running into, primarily that player1 is not static, does this mean I will have to individually make every player static or is there an easier way?
The primary issue however lies with my attempts to create a small program to change the Supply, The idea is for a user to enter an ID and then allow them to edit the supply, this went well for me when I was using an array but I am having issues understanding how to use data in a list<> and change it(basically trying to reach the values stored in the list from other methods if possible at all).
An easier way would be to initialize the list by
List<MP3_Players> PlayerList = new MP3Players[]{
new MP3_Players()
{
ID = 1,
Make = "GET Technologies .inc",
Model = "HF 410",
MBsize = 4096,
Price = 129.95m,
Supply = 500
}, <-- include more instances of MP3_Players here
}.ToList();
and furthermore, the indexer [] can be used to access the elements in a list very similar to an array.
To solve your "list problem" you could use classes and a dictionary:
public class MP3_Players
{
/* ... */
}
public static void mutate()
{
var PlayerList = new Dictionary<int, MP3_Players>;
PlayerList.Add(player1.ID, player1);
PlayerList.Add(player2.ID, player2);
PlayerList.Add(player3.ID, player3);
PlayerList.Add(player4.ID, player4);
PlayerList.Add(player5.ID, player5);
}
Then you can access them via their ID and change them:
var player = PlayerList[ID];
player.Supply--;
player.Price -= 10;
BUT to solve your bigger problem of "persistency" you should think of a "data-store" to persist you data, e.g. Entity Framework and a DB.
Have you considered using collection initializer for inlining the creation of the PlayerList?
Where static is concerned, static method cannot access non static instance members.
One way is to create dictionary like other user explain if the ID of the players are Unique, if they are not doesn't start this approach. This is requirement of dictionary !
The other way using List.
List<MP3_Players> newList = PlayerList.FindAll(x=>x.Model == Apple3);
newList.ToList().ForEach(x => x.Storage = 30);
This will return every Player with Model Apple3 and second row will change all the values for Storage.
In C#, Structs are Immutable. This means that they can't be edited. If you wish to make a change to an item, then it needs to be replaced by a totally new item. You can avoid this by using a class.
One problem that I have ran into editing collections in an enumeration is that the collection was modified and the enumeration can no longer continue. This was happening because I was using a foreach loop that evaluates each item in the collection. I avoided it by using for loops and fetching the element from the list using its index and performing my edit there.

Extending a property and in meanwhile insert a new item

This is my code:
var myList = myPage.News.Cast<MyNew>();
MyNew have somethings like 20 property (Name, Title, Date, Place, etc etc) but it miss one, the property (for example) Tel.
Can't recreate my whole structure (it also become from a DLL), so I'd like to faster add a property of MyNew called Tel, inside that list. So extend the class during the insert in a list.
No, but you could create an anonymous type that includes the original type plus your new column:
var myList = myPage.News
.Cast<MyNew>()
.Select( new { m => MyNew = m,
Tel = [formula for tel]
}
);
public class MyNewExtended: MyNew {
public String Tel { get;set; }
}
var myList = myPage.News.Cast<MyNewExtended>();
(but see Chris Sinclair's comment below)
You should be able to extend MyNew with a partial class like so:
public partial class MyNew
{
public int Tel { get; set; }
}
Tel will then be available like any other property.

Categories

Resources