Instantiating object in a for loop base on index [duplicate] - c#

This question already has answers here:
How to create variables with dynamic names in C#?
(6 answers)
Closed 8 years ago.
I'm trying to do something I 'm not even sure it's possible , therefore I would like to seek some suggestions.
I want to create 20 objects and each object names is assigned according to their number given. All twenty objects will be instantiated from the class called myClass, and they will have name called object_0,object_1,object_2 and so on.. with the properties i defined in the class given below. Is that possible?? Thanks
Let say i want to implement these codes, click is just like a Main void to trigger these codes
private void button_Click(object sender, EventArgs e)
{
for (int i = 0; i < 20; i ++)
{
myClass object_i = new myClass();
}
}
public class myClass
{
public myClass
{
}
}

I dont know what you are trying to do exactly, but use a List to store your object.
var myListOfObjects = new List<MyClass>();
for (var i = 0; i < 20; i++)
{
myListOfObjects.Add(new MyClass());
}
And if you look # your code ... your crteated objects lifetime is only inside the Loop :)
Referencing to the comment of #Alex-k you also could use a Dictionary if you want to store the objects by key
var myDictOfObjects = new Dictionary<string, MyClass>();
for (var i = 0; i < 20; i++)
{
myDictOfObjects.Add(string.Format("object_{0}", i), new MyClass());
}

Related

Insert an object in a list in chronological order [duplicate]

This question already has answers here:
insert into a List alphabetically C#
(5 answers)
Closed 1 year ago.
I have a list with objects inside which have a DateTime property.
Using a DataPicker and a TimePicker, I create a DateTime object, which I then insert into the ObservableCollection<>. However, I would like to insert the elements in the list in chronological order with respect to the DateTime. How can I find the right position to put it in the list?
public class HumorDiary
{
public DateTime Dt { get; set; }
}
HumorDiary obj= new HumorDiary();
obj.Dt= xx/xx/xxxx;
ObservableCollection<HumorDiary> listDiario = new ObservableCollection<HumorDiary>();
listDiario.Insert(Position????, obj);
(Answer edited after testing the code.)
You can sort the list yourself.
listDario.Add(obj);
listDario = new ObservableCollection<HumorDiary>(listDario.OrderBy(x => x.Dt));
To my surprise, this does not actually fire an additional CollectionChanged event. However, note that this creates a new list, and event handlers attached to the list will probably be unlinked. I would also say it's not terribly efficient. If you don't need the event functionality at all, use SortedList<TKey,TValue> instead.
You could also write an extension method like below, but it assumes the list is already sorted, so you'd have to make sure to use it for every insert.
public static void InsertByDate(this ObservableCollection<HumorDiary> source, HumorDiary obj)
{
int idx = 0;
while (idx < source.Count() && source[idx].Dt <= obj.Dt) {
idx += 1;
}
source.Insert(idx, obj);
}
There are more than one methods for achieving this but the simplest one is using OrderBymethod. Here is an example:
HumorDiary obj1 = new HumorDiary();
obj1.Dt = DateTime.Now;
HumorDiary obj2 = new HumorDiary();
obj2.Dt = DateTime.Now.AddHours(1);
HumorDiary obj3 = new HumorDiary();
obj3.Dt = DateTime.Now.AddHours(5);
ObservableCollection<HumorDiary> listDiario = new ObservableCollection<HumorDiary>();
listDiario.Add(obj3);
listDiario.Add(obj2);
listDiario.Add(obj1);
listDiario = new ObservableCollection<HumorDiary>(listDiario.OrderBy(obj => obj.Dt));
Notice that you have to cast iorderedenumerable to ObservableCollection after ordering.

Can't display 2 different objects on 2 different listboxes

To clarify before hand this is for an assignment if what I am doing is a bad way i apologize but its all part of the criteria.
Having an issue with WinForms being able to handle having 2 listBoxes display 2 different objects data. I can successfully add data to either one of the listBoxes without and issue but as soon as i try and add data to the other, i am met with this error.
System.NullReferenceException: 'Object reference not set to an instance of an object.'
c was null.
Photo of Gui
private void DisplayBook()//display method
{
//current index is equal to 0 and increments everytime an item is added ( max of 20)
for (int i = 0; i < currentIndex; i++)
{
//Book is a class with getters and setters, myBooks is an array
Book b = myBooks[i];
//printbook is a print method on the Book class
lstbook.Items.Add(b.Printbook());
}
}
private void DisplayCustomer()//display method
{
lstcustomer.Items.Clear();
for (int i = 0; i < currentIndex; i++)
{
Customer c = myCustomer[i];
lstcustomer.Items.Add(c.Printcustomer());
}
}
example of my two display methods for each listBox.
I have used break points to try and determine the issue but it has been quite elusive, only throwing the above exception on these two lines.
Customer c = myCustomer[i];
Book b = myBooks[i];
You seem to be using the same counter (currentIndex) for both Customer and Book. So when you first add a customer and then a boox, the counter will be 2 but there's only one item in each list.
To make it easier to display the objects, add overrides for the ToStringmethod on both your objects, because then we can add the entire object to the listbox:
public override string ToString() {
return this.PrintBook(); // or this.PrintCustomer();
}
You could store the objects in a list instead, then you wouldn't have to use a counter:
IList<Customer> customers = new List<Customer>();
private void AddCustomer(Customer customer) {
customers.add(customer);
}
We could then use a foreach loop to add all items to the listbox, but since we already have all items in a list, we can set that as DataSource for the listbox:
lstcustomer.DataSource = customers;

Using ToList() when copying Lists [duplicate]

This question already has an answer here:
Entity Framework, get list for database first case
(1 answer)
Closed 5 years ago.
I have a program in C# (Visual Studio) and part of the code looks like this:
Class 1:
private void part_TextChanged(object sender, EventArgs e)
{
List<string> parameters = part.selectedParameters;
// Lots of code
List<string> allParameters = parameters.ToList();
for (int k = 0; k < limit; k++)
{
allParameters.Add("text");
}
}
Class 2:
public bool DoAnalysis()
{
List<string> partParameters = part.selectedParameters;
// Lots of code
List<string> allPartParameters = partParameters;
for (int k = 0; k < limit; k++)
{
allPartParameters.Add("text");
}
}
My question is concerning the use of ToList(). I want to copy List1 to List2 and working with List2 without List1 being changed too. Applying this to my code, I used .ToList() to deal with this. Adding ToList() was not a problem in Class 1 --> parameters.ToList() but when I want to add it in Class 2 to List<string> allPartParameters = partParameters, it is not possible. I only get the options ToArray() and ToString().
So, why can I add ToList() to a List in one part of the code and not in the other? Am I missing some property dependency somewhere else in the code?
Usually with dependency problems you can right click the red highlighted code and choose "Quick Actions and Refactoring" then a list will come up of dependencies you can possibly use. This will save you time typing it and has helped me tons.

C# How to programmatically build property name [duplicate]

This question already has answers here:
Get property value from string using reflection
(24 answers)
Closed 7 years ago.
I have an object called "Agent". Agent has among others, 10 properties named lab1 thru lab10. I need to assign these properties to text boxes on a form txtFieldLabel1 thru txtFieldLabel10. In the example below the left side of the operator in the loop is fine. I can't figure out the right side. I need to dynamically build the property name based on the index of the loop. This seems it should be fairly simple and similar to the left side of the operator.
for (int i = 1; i <= 10; i++)
{
tlp.Controls["txtFieldLabel" + i.ToString()].Text = Agent.lab + i.ToString();
}
Agent.GetType().GetProperty("lab" + i).GetValue(Agent, null);
That will get the value of the property that, using reflection, is defined as labX, where X is the value of i.
Edit: changed to GetValue(Agent, null) instead of GetValue(Agent), as the overload for the single object parameter was introduced in .NET 4.5.
You could use reflection as others mentioned, but it would be easier if you created Dictionary<int, string> inside your Agent class and define those KeyValuePairs with keys from 1 to 10 and desirable values corresponding to those keys. Here is an example:
public class Agent
{
public Dictionary<int, string> Lab = new Dictionary<int, string>();
public Agent()
{
this.Lab.Add(1, "Value 1");
this.Lab.Add(2, "Value 2");
this.Lab.Add(3, "Value 3");
// ...
this.Lab.Add(10, "Value 10");
}
}
Then you could call it like this:
var agent = new Agent();
for (int i = 1; i <= 10; i++)
tlp.Controls["txtFieldLabel" + i].Text = agent.Lab[i];
This seems it should be fairly simple and similar to the left side of the operator.
It's not simple at all; you can do it using reflection, but that's pretty advanced programming.
I suspect there are more meaningful property names available to you than lab1, lab2, etc. and strongly recommend you use them. Anyone who has to come back to this code in a few months will be grateful.
You can get the properties' values using reflection:
var agent = new Agent();
//...
var value = agent.GetType().GetProperty("lab" + i).GetValue(agent);
(Note: Agent is the class-name, while agent is the variable/instance)
Another (better/cleaner?) solution might be to implement the lab-properties as an array or List<string>, e.g:
class Agent {
public List<string> Labs {get;set;}
}
Then you could iterate over all Labs:
for (var i=0; i<agent.Labs.Count; i++) {
tlp.Controls["txtFieldLabel" + (i+1)].Text =
agent.Labs[i];
}

C# List<GenericClass>(100) Construction Principles

If I do the following:
List<GenericClass> listObj = new List<GenericClass>(100);
// Do I need this part too?
for (int i = 0; i < 100; i++)
{
listObj[i] = new GenericClass();
}
Basically I am asking if the C# compiler will automatically fire the GenericClass constructor for each of the 100 GenericClass objects in the list. I searched in the MSDN documentation as well as here on StackOverflow.
Thanks for any help.
That's not how List works. When you specify a capacity, it's an initial capacity, not the number of items in the list. The list contains no elements until you add them via the Add method. Lists do not have a maximum capacity. And since you're adding objects via the Add method, yes, you would have to new them up first.
In fact, doing what you put in your question would throw an ArgumentOutOfRange exception.
For what you're doing, you'd need to use an array.
var listObj = new List<GenericClass>();
listObj[0] = new GenericClass(); // ArgumentOutOfRange exception
This will work:
for (int i=0;i<100;i++)
{
listObj.Add(new GenericClass());
}
This is what you were attempting to do:
var arrayObj = new GenericClass[100];
for (int i = 0; i < 100; i++)
{
arrayObj[i] = new GenericClass();
}
Yes you do need to create and add each instance to the list. Take a look at the remarks section for this constructor style: http://msdn.microsoft.com/en-us/library/dw8e0z9z.aspx
You are specifying how many elements you expect to put in the list so that the list does not have to resize behind the scenes every time you add a new GenericClass instance to it.
No! It specify the initial capacity.
MSDN article:
The capacity of a List is the number of elements that the List
can hold. As elements are added to a List, the capacity is
automatically increased as required by reallocating the internal
array.
Since you cannot do it directly with List you can use a helper method to have a generator and use the List(IEnumerable collection) overload.
class Program
{
static void Main(string[] args)
{
var list = new List<string>
(
Generator.New(() => new string('a', 5), 100)
);
list.ForEach((x) => Console.WriteLine(x));
}
}
public static class Generator
{
public static IEnumerable<T> New<T>(Func<T> generator, int nCount)
{
for (int i = 0; i < nCount; i++)
{
yield return generator();
}
}
public static IEnumerable<T> New<T>(Func<int,T> generator, int nCount)
{
for (int i = 0; i < nCount; i++)
{
yield return generator(i);
}
}
}
This does work but it is not so pretty as it could be if List would support this functionality out of the box. The example program will print 100 lines consisting of 5 a characters.

Categories