Storing values in list<> and changing them - c#

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.

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# Winform - How to bind my object's enum property to a DataGridView's Combobox?

So I'm attempting to code a fully-automated DnD sheet, and for the Extra Bonus section I figured I'd use a DataGridView where the user can freely add new bonuses to their character (including its equipped state, its name, its affected value, and its bonus value).
Here's my class. The 3rd property is an enum with some placeholder values for the sake of testing it.
public class ExtraBonus
{
public bool isEquipped { get; set; }
public string bonusName { get; set; }
public AffectedValues.values affectedValue { get; set; }
public string bonus { get; set; }
}
Here's my list with some more pre-entered placeholder values:
public static List<ExtraBonus> list = new List<ExtraBonus>()
{
new ExtraBonus { isEquipped = true, bonusName = "Divine Smite", affectedValue = AffectedValues.values.Heavy, bonus = "+1d6"},
new ExtraBonus { isEquipped = false, bonusName = "Hexblade", affectedValue = AffectedValues.values.None, bonus = "+3"},
new ExtraBonus { isEquipped = true, bonusName = "Hex", affectedValue = AffectedValues.values.Light, bonus = "+1d8"}
};
And here is where the list is bound to my DataGridView:
var bindingList = new BindingList<ExtraBonus>(ExtraBonusList.list);
var source = new BindingSource(bindingList, null);
ExtraBonusesGridView.DataSource = source;
With this I currently get the following (don't mind the formatting):
This seems to work but the program returns an error message when it's attempting to fill the third column. Says the value in DataGridViewComboBoxCell isn't valid (paraphrasing because the actual error log is in french).
I've been looking up all kinds of tutorials and I just can't find anything for this. I want my 3rd property (an enum of possible values that can be affected) to be bound to this ComboBox column where the user can freely select which value gets affected by this bonus.
How can I do this?
Thanks!

How to add data one level down to IEnumerable type?

I am working on .Net project. I have my Product model below.
class Product
{
public IEnumerable<OptionData> Options { get; set; }
}
Then I have OptionData model below.
public class OptionData
{
public Colour PrimaryColour { get; set; }
public Colour SecondaryColour { get; set; }
public IEnumerable<SizeData> Sizes { get; set; }
}
Then I have SizeData model below.
public class SizeData
{
public string KeycodeNumber { get; set; }
public Size Size { get; set; }
}
Then I have my size model below.
public class Size
{
public string Name { get; set; }
}
Then I am sending data using these models to some messaging system. In my case it is confluent kafka.
Options = new Option[]
{
new Option
{
PrimaryColour = new CodeNamePair
{
Name = "White",
},
SecondaryColour = new CodeNamePair
{
Name = "red",
},
Sizes = new SizeElement[]
{
new SizeElement
{
Size = new KafkaProductEvent.Size
{
Name = "10"
},
KeycodeNumber = 232
}
}
}
}
Then through consumer I am extracting data. I am able to get PrimaryColour or SecondaryColour as below.
IEnumerable<object> options = (IEnumerable<object>)((GenericRecord)response.Message.Value["Product"])["Options"];
foreach (var data in options)
{
OptionData optionData = new OptionData()
{
PrimaryColour = new Colour()
{
Name = (string)((GenericRecord)((GenericRecord)data)["PrimaryColour"])["Name"],
},
SecondaryColour = new Colour()
{
Name = (string)((GenericRecord)((GenericRecord)data)["SecondaryColour"])["Name"]
}
};
}
Then I want to get Sizes data as well. I tried something like this.
Sizes = new SizeData[]
{
new SizeData()
{
Size = new ProductEvents.Size()
{
Name = "";
}
}
}
I am not sure how to get size name from above. Can someone help me to find it out. Any help would appreciated. Thanks
Main challenge that I see in the code posted by you is the kind of APIs exposed by the client adapter you are using for deserializing the complex data model with multiple aggregated objects, challenge with what you are doing is, typecasting every record in every hierarchy to GenericRecord, then typecast to actual .Net type object, which means as the aggregated hierarchy grows, it will make it extremely complex to deserialize the actual object, especially with aggregated collections:
Also a point related to deserializing Options :
class Product
{
public IEnumerable<OptionData> Options { get; set; }
}
Your code is:
IEnumerable<object> options = (IEnumerable<object>)((GenericRecord)response.Message.Value["Product"])["Options"];
What I am wondering is why you cannot type cast to IEnumerable<OptionData>, to make it little simple and let's assume if that's not possible, then while enumerating through the IEnumerable<object> options why it can't still be type casted to the OptionData object, challenge with the adapter or approach you are using is that it needs complete object and hierarchy / property name awareness to de-serialize, when ideally once you fill the top level object like Product in this case, rest all shall recursively fill in, a good example is Newtonsoft Json, it will automatically fill object of any complexity, will make anything unavailable as null / default and require the minimal deserialization code.
Actually what you can do is, develop your own adapter that reads property details via reflection and fill data that is available in the input or discard it. For now assuming, this is all that you have as APIs, then following shall be the approach:
IEnumerable<object> options = (IEnumerable<object>)((GenericRecord)response.Message.Value["Product"])["Options"];
foreach (var data in options)
{
OptionData optionData = new OptionData()
{
PrimaryColour = new Colour()
{
Name = (string)((GenericRecord)((GenericRecord)data)["PrimaryColour"])["Name"],
},
SecondaryColour = new Colour()
{
Name = (string)((GenericRecord)((GenericRecord)data)["SecondaryColour"])["Name"]
},
Sizes = new List<SizeData>() // Initialize Collection Here
};
IEnumerable<object> SizesEnumerable = (IEnumerable<object>)(((GenericRecord)data)["Sizes"]);
foreach (var size in SizesEnumerable)
{
var sizeValue = new SizeData
{
KeycodeNumber = (string)((GenericRecord)size)["KeycodeNumber"],
Size = new Size
{
Name = (string)((GenericRecord)((GenericRecord)size)["Size"])["Name"]
}
};
((List<SizeData>)optionData.Sizes).Add(sizeValue); // Add Data here
}
}
What's the difference ?
You are trying to use the object initializer to fill in the IEnumerable<SizeData> Sizes to fill in the collection, but that doesn't provide option to do further processing as required in your case
Also note I have made IEnumerable<SizeData> Sizes as List<SizeData>, since we cannot use object initializer, so we cannot use array, since we don't know the size in advance
Going further used the same logic as yours to fill the data

Assigning value to a two dimensional array

I have a client server program. The client are the students so I've made a seat plan that generates two dimensional button arrays.
Button[,] btnSeat = new Button[8, 6];
How can I assign the client's hostname to each button once a client is online? Assuming there is already a hostname. Assign the first user who goes online to the first array[0,0] and the second to array[0,1] and so on....?
This is the layout of my seat plan
I also need to retrieve array[x,y] that is equals to that hostname. Please help, thank you.
Here is an example of what I think would be a better data structure:
For the Computer, you need to hold some information, so create a class for the computer:
public class Computer
{
public string HostName { get; set; }
public int Row { get; set; }
public int Column { get; set; }
//Whatever else you want to add, like
public bool IsActive { get; set; }
public bool IsScrewingAround { get; set; }
}
Then you can use a dictionary to store the data:
public Dictionary<string, Computer> _computers =
new Dictionary<string, Computer>(StringComparer.OrdinalIgnoreCase);
And you add computers to it like:
_computers.Add("someHostName", new Computer()
{
HostName = "someHostName",
Row = 0,
Column = 4,
IsActive = true,
IsScrewingAround = false
});
Then you can look up Computers by host name in an O(1) operation like:
var cpu = _computers["hostName"];
Or get a list of computers that are screwing around:
var screwOffs = _computers.Values.Where(c => c.IsScrewingAround);
Want all the computers in row 4?
var row4 = _computers.Values.Where(c => c.Row == 4);
This gives you an advantage over an array that it can grow based on the number of Computers added to it in case your room shape changes.
Really this could be a List<Computer> if you don't need the O(1) look-up for the host name, which I'm guessing would be fine given the relatively small number of items you have in the classroom.

Create a class with array of objects

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.

Categories

Resources