Acessing object through object array - c#

I want to learn classes atm and here is what I came up with:
Class level to create a level. This class has an object array that fills itself with rooms (raeume) which is the other class. Now, I want to access the objects in the object array from room, after I inserted them. Here is what I want to type:
wohnung.rooms[i].raumname.toString();
Here are the two classes
class raum
{
static object[] o_nebenraum = new object[3]; //N-O-S-W
static string s_raumname = "";
public object[] nebenraume
{
get
{
return o_nebenraum;
}
set
{
o_nebenraum = value;
}
}
public string raumname
{
get
{
return s_raumname;
}
set
{
s_raumname = value;
}
}
}
class level
{
static object[] o_rooms = new object[100];
public object[] rooms
{
get
{
return o_rooms;
}
set
{
o_rooms = value;
}
}
}
Here is how I set everything up.
level wohnung = new level();
raum keller = new raum();
raum wohnzimmer = new raum();
raum kueche = new raum();
raum schlafzimmer = new raum();
wohnung.rooms[0] = keller;
wohnung.rooms[1] = wohnzimmer;
wohnung.rooms[2] = kueche;
wohnung.rooms[3] = schlafzimmer;
keller.raumname = "Keller";
wohnzimmer.raumname = "Wohnzimmer";
kueche.raumname = "Küche";
schlafzimmer.raumname = "Schlafzimmer";
for (uint i = 0; i < 3; i++)
{
Console.WriteLine("Wohnung beinhaltet jetzt " + *MISSING CODE PART, I WANT TO GET THE .raumname out of the object array from wohnung.room*);
}
Console.ReadKey();

You have to use generic typed list List<T> (See on MSDN) instead of array, in this case you'll have the indexed access for the typed list elements
So instead of:
static object[] o_rooms = new object[100];
public object[] rooms
Use:
static IList<raum> o_rooms = new List<Raum>(100);
public IList<raum> rooms

Try this(in the for Loop):
Console.WriteLine("Wohnung beinhaltet jetzt " + (wohnung.rooms[i] as raum).raumname );
You would be better off using generics though in which case the class level would now look like:
class level
{
static List<raum> o_rooms = new List<raum>();
public List<raum> rooms
{
get { return o_rooms; }
set { o_rooms = value; }
}
}
and the for loop can be replaced with a foreach loop as follows:
foreach(raum room in wohnung.rooms)
{
Console.WriteLine("Wohnung beinhaltet jetzt " + room.raumname );
}

Related

Using string array to set data members' values

I have a class named Person.
Which has data members as follows:
Boolean Old
Boolean Educated
Boolean Employed
Boolean Married
Now I have a string array 'Values' which contains some of these data members.
My task is to set data members present in an array 'Values' to true for a particular object of class Person.
As in I would be having one array for each of the objects p1,p2,p3... of class Person.
For now I am using 'if' condition for each of the data members to check whether they are present in an array. And setting them to true if they do.
How can I use these string values to set data members to true in more efficient way?
Eg. p1 and p2 are objects of class Person
For p1
Values = {Old, Employed}
In this case I will set p1.Old and p1.Employed to true.
For p2
Values= {Employed,Married}
In this case I will set p2.Employed and p2.Married to true.
Person setMembers(string[] Values)
{
var p1 = new Person();
string s1 = "Old";
int i1 = Array.IndexOf(Values, s1);
string s2 = "Educated";
int i2 = Array.IndexOf(Values, s2);
string s3 = "Employed";
int i3 = Array.IndexOf(Values, s3);
string s4 = "Married";
int i4 = Array.IndexOf(Values, s4);
if (i1 > -1)
{p1.Old = true;};
if (i2 > -1)
{p1.Educated = true;};
if (i3 > -1)
{p1.Employed = true;};
if (i4 > -1)
{p1.Married = true;};
return p1;
}
One way to optimize conversion of string values to setting properties would be a hash dictionary that maps strings to actions, like this:
private static readonly IDictionary<string,Action<Person>> ActionByName =
new Dictionary<string,Action<Person>>() {
{"Educated", p => { p.Educated = true; } }
, {"Employed", p => { p.Employed = true; } }
, {"Married", p => { p.Married = true; } }
, {"Old", p => { p.Old = true; } }
};
With this dictionary in hand, you could process the values like this:
Person p1 = ...
foreach (var val in valuesForP1) {
Action<Person> a;
if (ActionByName.TryGetValue(val, out a)) {
a(p1);
}
}
This way lookup of the thing to do is performed using hash table. Note that you can skip the dictionary and use switch instead, like this:
foreach (var val in valuesForP1) {
switch(val) {
case "Educated": p1.Educated = true; break;
case "Employed": p1.Employed = true; break;
case "Married": p1.Married = true; break;
case "Old": p1.Old = true; break;
}
}
If you can use System.Linq, then you would have Contains function and then you can do something like this
objPerson.Old = Values.Contains("Old");
objPerson.Educated = Values.Contains("Educated");
With reflection... but the string values have to match exactly the property names
class Program
{
static void Main(string[] args)
{
var testPerson = CreatePerson(new[] { "Old", "Employed" });
Console.WriteLine(testPerson.Old);
Console.WriteLine(testPerson.Educated);
Console.WriteLine(testPerson.Employed);
Console.WriteLine(testPerson.Married);
}
public static Person CreatePerson(string[] args)
{
Person result = new Person();
Type personType = typeof(Person);
foreach (string item in args)
{
personType.GetProperty(item).SetMethod.Invoke(result, new object[] { true });
}
return result;
}
}
public class Person
{
public bool Old { get; set; }
public bool Educated { get; set; }
public bool Employed { get; set; }
public bool Married { get; set; }
}
I think you may write a method that sets your properties accordingly:
class Person {
bool old, educated, employed, married;
void SetValues(string[] values) {
this.old = values.Contains("Old");
this.educated = values.Contains("Educated");
this.employed = values.Contains("Employed");
this.married = values.Contains("Married");
}
Now you may call this as follows:
Person p1 = new Person();
p.SetValues(new[] { "Old", "Married" };

how can i get an access to the elements of array in the class

I have a problem which I don't know how to solve. I have a class. This class has two arrays. I would like to get access via properties. How can I do it? I tried to use indexers, but it is possible if I have only one array. Here what I want to do:
public class pointCollection
{
string[] myX;
double[] myY;
int maxArray;
int i;
public pointCollection(int maxArray)
{
this.maxArray = maxArray;
this.myX = new string[maxArray];
this.myY = new double[maxArray];
}
public string X //It is just simple variable
{
set { this.myX[i] = value; }
get { return this.myX[i]; }
}
public double Y //it's too
{
set { this.myY[i] = value; }
get { return this.myY[i]; }
}
}
With this code, my X and Y are only simple variables, but not arrays.
If I use indexers, I get access only to one array:
public string this[int i]
{
set { this.myX[i] = value; }
get { return this.myX[i]; }
}
But how can I get access to second array?
Or I can't use property in this case? And I need only use:
public string[] myX;
public double[] myY;
An example with Tuples.
public class pointCollection
{
Tuple<String,Double>[] myPoints;
int maxArray;
int i;
public pointCollection(int maxArray)
{
this.maxArray = maxArray;
this.myPoints = new Tuple<String,Double>[maxArray];
}
public Tuple<String,Double> this[int i]
{
set { this.myPoints[i] = value; }
get { return this.myPoints[i]; }
}
}
And to access the points you do...
pointCollection pc = new pointCollection(10);
// add some data
String x = pc[4].Item1; // the first entry in a tuple is accessed via the Item1 property
Double y = pc[4].Item2; // the second entry in a tuple is accessed via the Item2 property
If I got it right, you need some kind or read/write-only wrapper for arrays to be exposed as properties.
public class ReadWriteOnlyArray<T>{
private T[] _array;
public ReadWriteOnlyArray(T[] array){
this._array = array;
}
public T this[int i]{
get { return _array[i]; }
set { _array[i] = value; }
}
}
public class pointCollection
{
string[] myX;
double[] myY;
int maxArray;
public ReadWriteOnlyArray<string> X {get; private set;}
public ReadWriteOnlyArray<double> Y {get; private set;}
public pointCollection(int maxArray)
{
this.maxArray = maxArray;
this.myX = new string[maxArray];
this.myY = new double[maxArray];
X = new ReadWriteOnlyArray<string>(myX);
Y = new ReadWriteOnlyArray<double>(myY);
}
}
and usage
var c = new pointCollection(100);
c.X[10] = "hello world";
c.Y[20] = c.Y[30] + c.Y[40];
The closest you'll come without either changing your data structure or moving to methods is to make a property that returns each array, much like you did in your first code block, except without the [i].
Then, you do var x = instanceOfPointCollection.MyX[someI]; for example.

How to add Values to list<valuepair> object

I have the List<ValuePair> object: listUserRoleValuePair. I have to add ixUser and name as my value pair in the list in foreach loop. How I can Add this?
List<ValuePair> listUserRoleValuePair = new List<ValuePair>();
var ixUserList= _mapper1.FindUserRoleLike(sName);
User result = null;
foreach (var ixUser in ixUserList)
{
result = new UserMapper(connection).FindById(ixUser);
var name = result.SFirstName + " " + result.SLastName;
//listUserRoleValuePair.Add(ixUser);
// listUserRoleValuePair.Add(
}
my ValuePair class is as below
public class ValuePair
{
private string _index;
private string _sName;
public ValuePair(string index, string sName)
{
_index = index;
_sName = sName;
}
public string Index
{
get { return _index; }
set { _index = value; }
}
public string SName
{
get { return _sName; }
set { _sName = value; }
}
}
You can use the KeyValuePair class:
List<KeyValuePair<string,string>> listUserRoleValuePair = new List<KeyValuePair<string,string>>();
And then:
listUserRoleValuePair.Add(new KeyValuePair<string,string>(name, ixUser);
You can also use a Dictionary instead of a List.
Provided ixUser is the index string, use this code:
List<ValuePair> listUserRoleValuePair = new List<ValuePair>();
var ixUserList= _mapper1.FindUserRoleLike(sName);
User result = null;
foreach (var ixUser in ixUserList)
{
result = new UserMapper(connection).FindById(ixUser);
var name = result.SFirstName + " " + result.SLastName;
listUserRoleValuePair.Add(new ValuePair(ixUser, name));
}
listUserRoleValuePair.Add(new ValuePair(index, name));
Im, not clear what the index value is for your objects, but whatever it is, just replace it in the line above
you can add only items that support the child object type in your case you can use one of these.
collection.Add(new ValuePair(index, Name))
or
collection.Add(new ValuePair(){Index = index,SName= Name});
or very simple create object and pass as
Valuepair valpair = new ValuePair();
valpair.Index = index;
valpair.SName = name;
collection.Add(valpair);
Try this
var pair = new ValuePair();
// somehow intialize pair
listUserRoleValuePair.Add(pair);
listUserRoleValuePair.Add(new ValuePair(ixUser, name));

How do I create an array of objects in constructor?

I have two classes:
game
element
I want to be able to define an array of element objects in a game object. When I try this I get the warning message "..is never assigned to, and will always have its default value null"; in the local variables in the debugger I can see that the array exists, but all entries are null. The class Element works as I would expect. If I assign element objects to an array in Main it works, but not when I move the code to the Game constructor.
What am I doing wrong? I'm new to C# so it could be something very basic. Code below. Many thanks.
class Element
{
public Element()
{
elements = new List<int>(3);
elements.Add(1);
elements.Add(2);
elements.Add(3);
}
List<int> elements;
public void PrintElement()
{
for (int i = 0; i < 3; i++)
{
Console.WriteLine("Element {0}: {0}", i + 1, elements[i]);
}
}
}
class Game
{
public Game()
{
Element1 = new Element();
Element2 = new Element();
Element3 = new Element();
Element[] ThisGame = new Element[3];
ThisGame[0]= Element1;
ThisGame[1] = Element2;
ThisGame[2] = Element3;
}
public Element[] ThisGame;
private Element Element1;
private Element Element2;
private Element Element3;
public void PrintGameElement(int number)
{
ThisGame[number].PrintElement();
}
}
class Program
{
Game MyGame;
static void Main(string[] args)
{
Game MyGame = new Game();
MyGame.PrintGameElement(2);
Console.Read();
}
}
In Game, you are re-declaring ThisGame.
Change
Element[] ThisGame = new Element[3];
to
ThisGame = new Element[3];
Your Game constructor should look like this:
public Game()
{
Element1 = new Element();
Element2 = new Element();
Element3 = new Element();
ThisGame = new Element[3];
ThisGame[0]= Element1;
ThisGame[1] = Element2;
ThisGame[2] = Element3;
}
You need to set the list object to something when you initialize it.
List<int> elements = null;
OR
List<int> elements = new List<int>();
look at this code it may help you to make some order in your code:
Element class :
class Element
{
//property on element to save element data
public string ElementData { get; set; }
public Element(string data)
{
ElementData = data;
}
}
Game class :
class Game
{
//property on Game to save all elements
Element[] Elements { get; set; }
public Game(Element[] elements)
{
Elements = elements;
}
public void PrintGameElements()
{
foreach (var element in Elements)
{
Console.WriteLine(element.ElementData);
}
}
public void PrintElement(int index)
{
Console.WriteLine(Elements[index].ElementData);
}
}
Main function that initialize the array and pass it to the game :
static void Main(string[] args)
{
//initialize the array
var elements = new[]
{
new Element("data x"),
new Element("data y"),
new Element("data z")
};
//pass the elements to the game
var game = new Game(elements);
//print the second element
game.PrintElement(1);
//print all elements
game.PrintGameElements();
Console.ReadKey();
}
}

Refactoring WPF code behind

I have a method called get Data which executes my SQL and returns some rows of ContactLists containing Aggregated Labels.At the moment this method is in my code behind and would like to move it to a separate Data Access class. I would appreciate your assistance. Thanks!
Is normal, if i understand your code, you do this operation after ContactList initialization:
contactList.Labels = new ObservableCollection<Label>()
{
new Label() {
Name = dr["LABEL_NAME"].ToString(),
Count = Convert.ToInt32(dr["LABEL_COUNT"])
}
};
For each ContactList is always added one item, you will do something like this:
contactList.Labels = new ObservableCollection<Label>();
foreach(var item in <yourLabelDataSource>)
contactList.Labels.Add(new Label(...));
The solution is like this:
Dictionary<int, ContactList> myContactDictionary = new Dictionary<int, ContactList>();
using (DB2DataReader dr = command.ExecuteReader())
{
while (dr.Read())
{
int id = Convert.ToInt32(dr["CONTACT_LIST_ID"]);
if (!myContactDictionary.ContainsKey(id))
{
ContactList contactList = new ContactList();
contactList.ContactListID = id;
contactList.ContactListName = dr["CONTACT_LIST_NAME"].ToString();
contactList.Labels = new ObservableCollection<Label>()
{
new Label()
{
Name = dr["LABEL_NAME"].ToString(),
Count = Convert.ToInt32(dr["LABEL_COUNT"])
}
};
myContactDictionary.Add(id, contactList);
}
else
{
//Add new label because CONTACT_LIST_ID Exists
ContactList contactList = myContactDictionary[id];
contactList.Labels.Add(
new Label()
{
Name = dr["LABEL_NAME"].ToString(),
Count = Convert.ToInt32(dr["LABEL_COUNT"])
}
);
}
}
}
Ben, for your last question you can use this solution:
else
{
//Add new label because CONTACT_LIST_ID Exists
ContactList contactList = myContactDictionary[id];
string name = dr["LABEL_NAME"].ToString();
var label = contactList.Labels.Where(l => l.Name == name).FirstOrDefault();
if( label != null )
label.Count += Convert.ToInt32(dr["LABEL_COUNT"]);
else
{
contactList.Labels.Add(
new Label()
{
Name = dr["LABEL_NAME"].ToString(),
Count = Convert.ToInt32(dr["LABEL_COUNT"])
}
);
}
I hope this code is readable and helpfulL!
}
This is other response:
Create and Object Model that can contain your required data:
public class DataResult
{
public ObservableCollection<AggregatedLabel> AggregatedLabels { get; set; }
public ObservableCollection<ContactList> ContactLists { get; set; }
}
You can build a method that return DataResult object, in your method (GetData()), you can valorize the two different properties (AggregatedLabels and ContactsList) with your DB Result. In the and you can return DataResult Object.
A little example here:
public DataResult GetData()
{
DataResult result = new DataResult();
result.AggregatedLabels = new ObservableCollection<AggregatedLabel>();
result.ContactLists = new ObservableCollection<ContactList>();
// Manipulate data result with your method logic like in this examle:
foreach(var something in dbResult)
{
ContactList cl = new ContactList() {
//Binding from something
}
result.ContactLists.Add(cl);
}
return result; //return your Object Model with required Data!
}
I hope it is conceptually clear

Categories