Add objects to arraylist and read them - c#

I'm trying to add objects of DataPerLabel to my Arraylist allData, following the code of DataPerLabel:
class DataPerLabel
{
public String labelName;
public String labelAdress;
public String dataType;
public DataPerLabel(String labelName, String labelAdress, String dataType)
{
this.labelName = labelName;
this.labelAdress = labelAdress;
this.dataType = dataType;
}
public String getLabelName()
{
return labelName;
}
public String getLabelAdress()
{
return labelAdress;
}
public String getDataType()
{
return dataType;
}
}
In the following code I try to add the objects of DataPerLabel to my arraylist:
submitButton.Click += (sender, args) =>
{
String label = textboxLabel.Text;
String adress = textboxAdress.Text;
String dataType = "hey";
if (buttonsLabelBool.Checked)
{
dataType = "Bool";
}
else if (buttonsLabelReal.Checked)
{
dataType = "Real";
}
else if (buttonsLabelInt.Checked)
{
dataType = "Int";
}
allData.Add(new DataPerLabel(label, adress, dataType));
};
And finally I try to read out the arrayList by displaying it in a textbox, see the following code:
private void test()
{
Button btn = new Button();
btn.Location = new Point(500,500);
btn.Text = "test";
btn.Click += (sender, args) =>
{
foreach (var item in allData)
{
//Display arraylist per object here
//Something like : item.getLabelName();
}
};
}
I'm not sure what I'm doing wrong, hope you can help!

ArrayList stores a list of System.Object. You need to cast the object back to DataPerLabel as follows:
foreach (var item in allData)
{
((DataPerLabel)item).getLabelName();
}
Alternatively, you could specify the data type in the foreach instead of var as Jakub DÄ…bek pointed out in the comment as follows:
foreach (DataPerLabel item in allData)
{
item.getLabelName();
}
A better approach would be to use generic list/collection List<DataPerLabel> to store the data so that the casting can be avoided.

Yiu should use a List<T> instead of ArrayList. This way every item in your list has the right type already and you can access the members:
foreach (DataPerLabel item in allData)
{
item.GetLabelItem();
}
This assumes allData is defined like this:
allData = new List<DataPerLabel>();
instead of allData = new ArrayList()
If you really have to use an ArrayList than you should cast your item to the actual type. The code above actually does this allready. However you could also use this:
foreach (var item in allData)
{
((DataPerLabel)item).GetLabelItem();
}

Related

Returning objects from list to a listbox

I've been trying to create a method which adds items in to the listbox.
There is a class Member and each Member belongs to the ProjectGroup. Member has a method getName() which returns string name. So the problem appears when I try to add more than 1 person. The listbox gets stuck at first person in the list, and nothing new appears. The code looks like this:
public class ProjectGroup
{
List<Member> members = new List<Member>();
public void addMember(string name)
{
Member newPerson = new Member(name);
members.Add(newPerson);
}
public string getInfo()
{
foreach (Member item in members)
{
return item.getName();
}
return null;
}
}
And the code in the form:
ProjectGroup group = new ProjectGroup();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string name = textBox1.Text;
lbStudents.Items.Clear();
textBox1.Text = "";
group.addMember(name);
lbStudents.Items.Add(group.getInfo());
}
public List<string> getInfo()
{
var result= new List<string>();
foreach (Member item in members)
{
result.Add(item.getName());
}
return result;
}
and change it:
lbStudents.Items.AddRange(group.getInfo());

C# custom add in a List

I have the following list of strings :
var files = new List<string> {"file0","file1","file2","file3" };
I would like to be able to add new files to this list, but if the inserted file is present in the list, I would like to insert custom value that will respect the following format $"{StringToBeInserted}"("{SomeCounter}
For instance : try to add "file0" and "file0" is already I would like to insert "file0(1)". If I try again to add "file0" ... I would like to insert with "file0(2)" and so on ... Also, I would like to provide a consistency, for instance if I delete "file0(1)" ... and try to add again "item0" ... I expect that "item0(1)" to be added. Can someone help me with a generic algorithm ?
I would use a HashSet<string> in this case:
var files = new HashSet<string> { "file0", "file1", "file2", "file3" };
string originalFile = "file0";
string file = originalFile;
int counter = 0;
while (!files.Add(file))
{
file = $"{originalFile}({++counter})";
}
If you have to use a list and the result should also be one, you can still use my set approach. Just initialize it with your list and the result list you'll get with files.ToList().
Well, you should create your own custom class for it, using the data structure you described and a simple class that includes a counter and an output method.
void Main()
{
var items = new ItemCountList();
items.AddItem("item0");
items.AddItem("item1");
items.AddItem("item2");
items.AddItem("item0");
items.ShowItems();
}
public class ItemCountList {
private List<SimpleItem> itemList;
public ItemCountList() {
itemList = new List<SimpleItem>();
}
public void DeleteItem(string value) {
var item = itemList.FirstOrDefault(b => b.Value == value);
if (item != null) {
item.Count--;
if (item.Count == 0)
itemList.Remove(item);
}
}
public void AddItem(string value) {
var item = itemList.FirstOrDefault(b => b.Value == value);
if (item != null)
item.Count++;
else
itemList.Add(new SimpleItem {
Value = value,
Count = 1
});
}
public void ShowItems() {
foreach (var a in itemList) {
Console.WriteLine(a.Value + "(" + a.Count + ")");
}
}
}
public class SimpleItem {
public int Count {get; set;}
public string Value {get; set;}
}

C# Generic parameter from a string variable

I have two classes, Customer and Country. Customer has a property called HomeCountry, which i have decorated with a custom attribute called "Lookup" and takes a string parameter "Country". The purpose is, when I am using the Customer class, the item in HomeCountry must exist in the Country class (which happens to be a list).
I am using reflection to iterate the Customer class, it finds the attribute and i want it to check the value in the list of country items. So far I have:
foreach (PropertyInfo _pi in object.GetType().GetProperties()) {
IEnumerable<Attribute> _attrs = _pi.GetCustomAttributes();
foreach (Attribute _a in _attrs) {
Object obj = Activator.CreateInstance(_type, null);
// what goes here?
}
}
I have a method:
public T Populate<T>(params string[] _parameters)
I think i want to do
List<obj> v = populate<obj>();
or
List<typeof(obj)> v = populate<typeof(obj)>();
but obviously nothing works! Can anybody help me ?
Thanks
OK i will try and provide a full example:
I have a CUSTOMER_ORDER class:
public class CUSTOMER_ORDER {
public CUSTOMER_ORDER() {}
[Key(0)]
public string OrderNumber {get;set;}
public MPCCOM_SHIP_VIA ShipVia {get;set;}
}
Then the MPCCOM_SHIP_VIA class:
public class MPCCOM_SHIP_VIA {
public MPCCOM_SHIP_VIA() {}
[Key(0)]
public string ID {get;set;}
public string Description {get;set;}
}
I have a method called Populate< T > which takes a class and then uses reflection to loop all the properties and build a select statement, executes it, and then returns the data and populates the object:
public T Populate<T>(params string[] #Parameters)
{
Type _t = typeof(T);
dynamic _o = Activator.CreateInstance(typeof(T), null);
SqlBuilder _sb = new SqlBuilder();
_sb.Table = string.Format("{0}.{1}", _Owner, _t.Name.ToString());
foreach (PropertyInfo p in _t.GetProperties(Utilities.BindingFlags))
{
if (p.GetMethod.IsPrivate == false) _sb.Fields.Add(p.Name.ToString());
IEnumerable<Attribute> _attrs = p.GetCustomAttributes();
foreach (Attribute _a in _attrs)
{
if (_a.TypeId.ToString().Equals(typeof(Key).FullName))
{
int _position = ((Key)_a).Position;
try
{
string _parameter = #Parameters[_position];
_sb.Where.Add(string.Format("{0} = '{1}'", p.Name, _parameter));
}
catch {}
}
}
}
using (OleDbCommand _cmd = new OleDbCommand())
{
_cmd.Connection = this._cn;
_cmd.CommandText = _sb.SQL;
if (_trn != null) _cmd.Transaction = _trn;
_cmd.CommandType = System.Data.CommandType.Text;
using (OleDbDataReader _reader = _cmd.ExecuteReader())
{
if (_reader.Read())
{
for (int x = 0; x < _reader.FieldCount; x++)
{
foreach (PropertyInfo p in _t.GetProperties(Utilities.BindingFlags))
{
if (p.GetMethod.IsPrivate == false)
{
if (p.Name.Equals(_reader.GetName(x).ToString()))
{
dynamic _val = _reader.GetValue(x);
if (p.ReflectedType.BaseType.Name.Equals(""))
{
// what goes here!
}
try
{
p.GetSetMethod(true).Invoke(_o, new object[] { _val });
}
catch { }
break;
}
}
}
}
}
else
{
throw new DatabaseObjectNotFound(_t.Name.ToString(), string.Join(",",#Parameters));
}
}
}
return (T)_o;
}
So, as i read an order, the source DB gets the key to the MPCCOM_SHIP_VIA in the respective field, i want to call the same Populate method against the MPCCOM_SHIP_VIA object with the key. I hope this makes more sense demonstrating what i want to do. And thanks
After some hunting around, this is the answer i was looking for...
MethodInfo method = typeof(class).GetMethod("Populate");
method = method.MakeGenericMethod(p.PropertyType);
_val = method.Invoke(class, new object[] { _prms });
I guess my issue was i was asking the wrong question!

Is there a var.contains - C#

I have a question about the following code:
private void Filter (object sender, Android.Text.TextChangedEventArgs e)
{
List<Animal> animalList = new List<Animal>();
if(!string.IsNullOrEmpty(_editText.Text))
{
foreach (string str in _animalList)
{
if (str.Contains(_editText.Text))
{
animalList.Add (str);
}
}
}
_listView.Adapter = new AnimalAdapter(this, _animalList = animalList);
}
The Animal class:
public class Animal
{
private readonly int _intKey;
public int AnimalNumber { get; private set; }
public int StableNumber { get; private set; }
public int LactoseNumber { get; private set; }
public Animal ( int intKey, int animalNumber, int stableNumber, int lactoseNumber )
{
_intKey = intKey;
AnimalNumber = animalNumber;
StableNumber = stableNumber;
LactoseNumber = lactoseNumber;
}
public override string ToString ()
{
return "Number: " + AnimalNumber + "\nGroup: " + StableNumber + "\nLactation: " + LactoseNumber;
}
}
Declaration of _animalList:
private List<Animal> _animalList;
i need to check if the _animalList Contains the input of the _editText.Text.
But _animalList isn't a string so i need to use a var.
Is there something like a var.Contains or do i have to use something else?
Contains method is available for string type. You will need to cast your object to string.
A/c to your class definition you should do like:
foreach (Animal str in _animalList)
{
if (str.ToString().Contains(_editText.Text)) //using user defined "ToString()"
{
animalList.Add (str);
}
}
You can also check individual properties:
foreach (Animal str in _animalList)
{
if (str.AnimalNumber.ToString().Contains(_editText.Text)) //if "AnimalNumber" is like "_editText.Text"
{
animalList.Add (str);
}
}
Instead of trying to filter using ToString, it would be better to use the real property values. For example:
var number = Convert.ToInt32(_editText.Text);
var filteredList = _animalList
.Where(x => x.AnimalNumber == number ||
x.StableNumber == number ||
x.LactoseNumber == number)
.ToList();
Otherwise, user could type "Number" and since your ToString override contains that string, all of the items in the list would match positively.
(I didn't include any validation or error checking in the code above, so you should consider those as well).
var inputText = _editText.Text;
int enteredNumber;
// you should make sure that the inputText is always an int
var isInt = int.TryParse(inputText, out enteredNumber);
//for example, if you are going to find by AnimalNumber, which is an int, you can use this. .
if (isInt){
foreach (var animal in _animalList){
var animalNumber = animal.AnimalNumber;
if (animalNumber == enteredNumber)
{
animalList.Add(animal);
}
}
}
Edit (LINQ alternative):
if (isInt){
animalList.AddRange(from animal in _animalList
let animalNumber = animal.AnimalNumber
where animalNumber == enteredNumber
select animal);
}
_animalList.Select(a => a.ToString()).Contains(_editText.Text)
This expression returns true if the output of the ToString method of any animal object equals _editText.Text.
_animalList.Select(a => a.ToString()).Any(str => str.Contains(_editText.Text))
This expression returns true if the output of the ToString method of any animal object contains _editText.Text (as a substring). This is equivalent to Shaharyar's answer.
var animalList = _animalList.Where(a => a.ToString().Equals(_editText.Text)).ToList();
var animalList = _animalList.Where(a => a.ToString().Contains(_editText.Text)).ToList();
These statements filter the input list directly.

searching an arraylist

I have a arraylist in my web application project in asp.net/C#/VS2008 and I'm using .net 3.5
I'm adding contents to the arraylist using a class which is defined as follows:
using System.Web;
class ShoppingCartDataStore
{
private string componentName;
private string componentPrice;
private string componentFileSize;
private string componentDescription;
public ShoppingCartDataStore(string componentName, string componentPrice, string componentFileSize, string componentDescription){
this.componentName = componentName;
this.componentPrice = componentPrice;
this.componentFileSize = componentFileSize;
this.componentDescription = componentDescription;
}
public string ComponentName
{
get
{
return this.componentName;
}
}
public string ComponentPrice
{
get
{
return this.componentPrice;
}
}
public string ComponentFileSize
{
get
{
return this.componentFileSize;
}
}
public string ComponentDescription
{
get
{
return this.componentDescription;
}
}
}
and I'm adding contents to the arraylist by following code:
ArrayList selectedRowItems = new ArrayList();
selectedRowItems.Add(new ShoppingCartDataStore(componentName, componentPrice, fileSize, componentDescription));
Suppose I want to search this arraylist after adding few values in this manner with componentName as the key. I tried the following code but I'm just not able to find a way to do this:
ArrayList temporarySelectedItemsList = new ArrayList();
ArrayList presentValue = new ArrayList();
string key = componentName; //some specific component name
temporarySelectedItemsList = selectedRowItems;
for (int i = 0; i < temporarySelectedItemsList.Count; i++)
{
presentValue = (ArrayList)temporarySelectedItemsList[i];
}
var results = selectedRowItems.OfType<ShoppingCartDataStore>().Where(x=>x.ComponentName == "foo")
of course you could get rid of the OfType if you were using a generic list rather than a arraylist
EDIT: So, I have no idea why you would NOT use LINQ or generics if you are in 3.5. But if you must:
ArrayList results = new ArrayList();
foreach (ShoppingCartDataStore store in selectedRowItems)
{
if(store.ComponentName == "foo"){
results.Add(store);
}
}
I'm sick and this is untested, but I think it'll work. :)
List<ShoppingCartDataStore> aList = new List<ShoppingCartDataStore>();
// add your data here
string key = componentName; //some specific component name
// Now search
foreach (ShoppingCartDataStore i in aList)
{
if (i.ComponentName == key)
{
// Found, do something
}
}

Categories