Solved

C#: Object Oriented issue

Posted on 2010-09-07
26
434 Views
Last Modified: 2012-05-10
Hello everyone!

I have this basic class:
 
Public class Person{
  private int age;
  private string name;

  public Person(){
    this.age = 0;
    this.name = "";
  }
  
  public int Age { get{ return this.age; } set { this.age = value; } }
  public string Name { get{ return this.name; } set { this.name= value; } }

}

Open in new window


I need to get a list of persons. So I want to make something that result in a code like this:
 
Person p = new Person();
firstPersonName = p.listPersons[0].name;
firstPersonAge = p.listPersons[0].age;

secondPersonName = p.listPersons[1].name;
secondPersonAge = p.listPersons[1].age;

Open in new window


could someone guide me into how to achieve this?

thanks
0
Comment
Question by:karelog
  • 9
  • 7
  • 4
  • +5
26 Comments
 
LVL 29

Expert Comment

by:anarki_jimbel
ID: 33623072
Not quite clear what you want. Can you just use a generic List<Person>?
0
 
LVL 4

Accepted Solution

by:
yesthatbob earned 200 total points
ID: 33623094
I wouldn't recommend doing it how you've shown in your second code sample. Since the Person object represents a single person, it shouldn't also represent a collection of persons. Rather, I would create a separate collection and add person object references to it taht you can then get the persons from:
 

// Create a collection to hold a group of persons
List<Person> persons = new List<Person>();

// Create a new person and add to collection
Person p = new Person();
p.Age = 25;
p.Name = "Joe";
persons.Add(p);

// Create a second new person and add to collection
p.Age = 35;
p.Name = "Mary";
persons.Add(p);

// Get the data for the first person
string firstPersonName = persons[0].Name;
int firstPersonAge = persons[0].Age;

// Get the data for the first person
string secondPersonName = persons[0].Name;
int secondPersonAge = persons[0].Age;

Open in new window

0
 
LVL 2

Expert Comment

by:murphomatic
ID: 33623108
A couple of things ...

1.  You're going to need to create "listPersons" as a static member of the Person class.
2.  You cannot refer to a static member through an instance variable.  You have to use the type/class name instead.

Add code to your Person class as I have listed below.

Then when you reference the listPersons static member, do it like this:

firstPersonName = Person.listPersons[0].Name;
public static Person[] listPersons
{
  get
  {
      Person[] p = {new Person(), new Person()};
      
      p[0] = new Person();
      p[0].Name = "Jim";
      p[0].Age = 35;

      p[1] = new Person();
      p[1].Name = "Bob";
      p[1].Age = 25;

      return p;
  }
}

Open in new window

0
Master Your Team's Linux and Cloud Stack

Come see why top tech companies like Mailchimp and Media Temple use Linux Academy to build their employee training programs.

 
LVL 29

Expert Comment

by:anarki_jimbel
ID: 33623112
I'd use a collection like in the snippet:
        private void button1_Click(object sender, EventArgs e)
        {
            Person p1 = new Person();
            Person p2 = new Person();
            Person p3 = new Person();
            Person p4 = new Person();
            Person p5 = new Person();
            List<Person> persons = new List<Person>();
            
            persons.AddRange(new Person[]{p1,p2,p3,p4,p5});
            string firstPersonName = persons[0].Name;
            int firstPersonAge = persons[0].Age;

            string secondPersonName = persons[1].Name;
            int secondPersonAge = persons[1].Age;

        }

Open in new window

0
 
LVL 3

Expert Comment

by:vusov
ID: 33625942
As I truly understand you need to implement Persons list into the Person class. Therefore here is the solution:

class Person
    {
        public int Age { get; set; }
        public string Name { get; set; }

        public List<Person> Persons { get; set; }

        public Person(List<Person> persons)
        {
            Persons = persons;
            Persons.Add(this);
        }

    }

 List<Person> list = new List<Person>();
            
 Person p = new Person(list);
 Person p1 = new Person(list);

 string firstPersonName = p.Persons[0].Name;
 int firstPersonAge = p.Persons[0].Age;

 string secondPersonName = p.Persons[1].Name;
 int secondPersonAge = p.Persons[1].Age;

Open in new window

0
 
LVL 8

Expert Comment

by:Gururaj Badam
ID: 33625959
@karelog - define your requirement precisely.
0
 

Author Comment

by:karelog
ID: 33627099
first of all I want to thank everybody for the answers.

Now to the issue:

once I've read the comments I think I have more clear what I need to.

I have this class Person and I need to go to the database and get a pool of persons.
So I was wandering if I can do something like this or is against the OO philosophy.
 [embed=snippet 1015898]

what do you all think of this?
is this against OO programming?
will this allow me to do this:

Person p = new Person();
firstPersonName = p.ListOfPersons[0].name;
firstPersonAge = p.ListOfPersons[0].age;

secondPersonName = p.ListOfPersons[1].name;
secondPersonAge = p.ListOfPersons[1].age;
Public class Person{
  private int age;
  private string name;

  private List<Person> listOfPersons;

  private bool flag; //used to know if go to database and get the list

  public Person(){
    this.age = 0;
    this.name = "";
    this.listOfPersons = new List<Person>();  //I don't know the number of elements the list can get.
    this.flag = false;

  }
  
  public int Age { get{ return this.age; } set { this.age = value; } }
  public string Name { get{ return this.name; } set { this.name= value; } }
  public List<Person> ListOfPersons{
    get{
      //Connnect to database and list persons...
      if (flag == false){
        this.listOfPersons = getPersonsFromDatabase();
        this.flag = true;
      }
      return this.listOfPersons;
    }
  }
}

Open in new window

0
 
LVL 3

Expert Comment

by:vusov
ID: 33627297
Actually it will work, but I dont think that it's good solution to fill ListOfPersons in the Person class. All filling action should be done in the separate DataAccess layer, that will return filled Person object.
0
 

Author Comment

by:karelog
ID: 33627383
I know.

The code I exposed is an example, actually I have

Connect layer -> Provides functions to execute Querys and nonQuerys to the database Server.
Data Layer -> Provides Classes to store the Database Info (in this case, Person is a sub-class of this Layer)
Query Layer -> Provides Functions that makes interact the Data Layer with the Connect Layer. (I don't know how to call this layer XD)

so the getPersonsFromDatabase() is actually a member of QueryLayer and tells the ConnectLayer to execute a query to the database. The Connect Layer will return a DataReader, so the QueryLayer will get this DataReader and will process it and store the info into the DataLayer. In this case, List all Persons.

Is this good?
0
 
LVL 3

Assisted Solution

by:vusov
vusov earned 100 total points
ID: 33627504
Yes, sure. I call Query Layer as DataAccess Layer as usual. As I see now maybe Query Layer  - is better.
But why do you need ListOfPersons as a member of Person class? Why you cannot use ListOfPersons as separate object?
0
 
LVL 9

Expert Comment

by:richard_hughes
ID: 33627587
Hello karelog

Have a look at the attached code. This will help you understand what you need:

Thanks,

Richard Hughes
public class Person
    {
        public string FirstName
        {
            get { return _firstName; }
            set { _firstName = value; }
        }
        private string _firstName = String.Empty;

        public bool Save(DbConnection con)
        {
            // save here
        }

        public static Person GetById(int personId, DbConnection con)
        {
            // get person here
        }

        public static List<Person> GetAll(DbConnection con)
        {
            // get all persons here
        }
    }

Open in new window

0
 

Author Comment

by:karelog
ID: 33627590
because I want a clean code in the GUI layer.

I don't want to be declarating all kind of classes and Lists of this classes and then fill them and all just to get the length of my List.

I want to provide the final programmer the simpliest way to do their job >.<
And I want to learn good practices as well in the meanwhile.
0
 
LVL 9

Expert Comment

by:richard_hughes
ID: 33627643
Using the above code, you can do something like this:

There are many ways to expand the ORM later in the code above, like implementing an IsDirty property for instance.

Thanks
Person p1 = new Person();
Person p2 = new Person();

p1.FirstName = this.textPersonFirstName.Text;
p1.Save(myDbConnection);

p2.FirstName = "John";
p2.Save(myDbConnection);

List<Person> allPeople = Person.GetAll(myDbConnection);
foreach(Person p in allPeople)
{
    Console.WriteLine(p.FirstName);
}

Open in new window

0
 

Author Comment

by:karelog
ID: 33627650
@richard_hughes:
Thanks, but that uses a method which must be received into an object to process it.

The idea is to use a property, so I can use it and apply it in one sentence of code.
0
 
LVL 9

Expert Comment

by:richard_hughes
ID: 33627659
What do you mean?
0
 

Author Comment

by:karelog
ID: 33627783
The explanation is in the code.
Person p = new Person();

//Method:
string name = p.getName();

//Property:
string name2 = p.Name;

/* Note that the method can receive an argument. The property just gets or sets something without argument */

//To declare a property into the Person class
Public class Person{
  private string name;
  
  //Property:
  public string Name {get { return this.name; } set { this.name = value } }

  //Method: (Getter and Setter)
  public string getName() { return this.name; }
  public void setName(string name) { this.name = name; }
}

Open in new window

0
 
LVL 9

Expert Comment

by:richard_hughes
ID: 33627836
Your code does the same as what is posted above, except without the GetAll method.

It is important the keep your code segmented and in layers if you would like to follow good programming practice. There is nothing wrong with passing an argument into Person.GetAll();

The programmer using this will expect such behaviour, because this is a common, standard way of completing this task.

Thanks
0
 
LVL 9

Expert Comment

by:richard_hughes
ID: 33627868
And as a note, there is no need to have both:

public string Name
{
    get { return this.name; }
}

and have:

public string getName()
{
    return this.Name;
}

This code duplication will confuse programmers. For good programming practice, it is good to avoid code duplication as much as possible.

Using:

public string Name
{
    get { return this.name; }
}

instead of the method is a standard .NET method of completing this task. Unless there is a lot of processing involved in the property, it is best to stick to the 'get'.

Thanks
0
 

Author Comment

by:karelog
ID: 33628056
@richard_hughes:

Ok, now we are understanding each other. :D

first:
  I know I should not use both.

second:
  I know about Layers. I'm not mixing anything.

third:
  my doubt is still on:
    is good to have a list of persons in a class which represents one singe person?
    Maybe I should create a class [b]"CollectionOfPersons"[/b] inherits from List. But I don't know how to do it D:

I want to be able that the GUI programmer life easier by providing easy-to-follow code.
I think this can be achieved by providing tools that can make this (see code):

Why to declare a new list if I already have one in my Person class?


Person p = new Person();
string name = p.listOfPersons[index].name;

//If I use a method instead a property,
//the GUI programmer will have to do something like:

Person p = new Person();

List<Person> list = p.listOfPersons();

string name = list[index].name;

Open in new window

0
 
LVL 9

Assisted Solution

by:richard_hughes
richard_hughes earned 200 total points
ID: 33628187
What are you doing is declaring an instance of a person to get a list of people. It is a bit like parking a list of cars inside of a single one.

Haveing the list statically follows good programming practice.

Have a look at the following code to see how to create your person collection class.

Thanks
public class PersonCollection : List<Person>
{
}

Open in new window

0
 
LVL 3

Expert Comment

by:vusov
ID: 33628263
Ok, I think there is one important thing: Will the Person class be used in the client-server application?
If yes using the Person object with listOfPersons will be heavy-aggregated transferring via network.
0
 

Author Comment

by:karelog
ID: 33628411
@richard_hughes:
  you just read my mind!!! I just make that XD
  now I will try to follow from that point. I think I'll list the Persons in the constructor of the class or, as I say below, when a method is executed.


@vusov:
  Is an ASP.NET application, The database and web-server and in the same machine.
  I'm thinking in adding method in order to refresh the list only when the "refreshListOfPersons()" is executed (yes, I have to create that method)
0
 
LVL 33

Expert Comment

by:Todd Gerbert
ID: 33628912
Just gonna throw in my two cents...
Logically, it doesn't really make sense that a single person should contain a list of persons - as a programmer using your code, I wouldn't expect or necessarily understand that in order to find "Jane" in a list of people I need to refer to an instance of "Bob"
In these cases I generally use a seperate PersonsCollection class (usually inheriting from CollectionBase), then in practice I generally need to refer only to the collection without much of a need to ever directly instantiate a Person.
 

using System;
using System.Collections;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
	class Program
	{
		static void Main(string[] args)
		{
			PersonsCollection people = new PersonsCollection();

			Person santa = new Person("Santa", "Claus");
			people.Add(santa);

			
		}
	}

	public class Person
	{
		public string FirstName { get; set; }
		public string LastName { get; set; }
		public Person() { }
		public Person(string FirstName, string LastName)
		{
			this.FirstName = FirstName;
			this.LastName = LastName;
		}

		public override string ToString()
		{
			return String.Format("{0},{1}", this.LastName, this.FirstName);
		}
	}

	public class PersonsCollection : CollectionBase
	{
		public PersonsCollection()
		{
			// Get data from database, or use overloaded constructor to
			// provide the list at collection creation
			this.AddNew("Jane", "Doe");
			this.AddNew("John", "Smith");
		}

		public void AddRange(params Person[] People)
		{
			foreach (Person p in People)
				List.Add(p);
		}

		public Person AddNew(string FirstName, string LastName)
		{
			Person newPerson = new Person(FirstName, LastName);
			List.Add(newPerson);
			return newPerson;
		}

		public int Add(Person person) { return List.Add(person); }

		public Person this[string LastNameCommaFirstName]
		{
			get
			{
				foreach (Person p in List)
					if (p.ToString().ToLower() == LastNameCommaFirstName.ToLower())
						return (Person)p;
				return null;
			}
		}

		public Person this[int index]
		{
			get { return (Person)List[index]; }
		}

		protected override void OnValidate(object value)
		{
			if (value.GetType() != typeof(Person))
				throw new ArgumentException("value must be of type Person.", "value");
		}
	}
}

Open in new window

0
 

Author Comment

by:karelog
ID: 33638479
I wanted to share the final code with all of you.
Thanks ^^

Public class Person{
  Public string Name { get; set; }
  Public string Age { get; set; }

  Public Person() { }
}

Public class People : List<Person>{

  Public static People listFromDatabase(){
    DataAccessLayer d = new DataAccessLayer();
    return d.listPeople();
  }
}

public void main(){
  People p = People.listFromDatabase();
  
  foreach(Person pr in People){
    Document.WriteLine("Name: " + pr.Name);
    Document.WriteLine("Age: " + pr.Age);

  }
}

Open in new window

0
 
LVL 9

Expert Comment

by:richard_hughes
ID: 33638514
Excelent!

I am pleased that you found the answer.

That code is fine :)
0
 

Author Closing Comment

by:karelog
ID: 33638548
Thanks everybody for helping me with this ^^
0

Featured Post

Free Tool: Postgres Monitoring System

A PHP and Perl based system to collect and display usage statistics from PostgreSQL databases.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

This document covers how to connect to SQL Server and browse its contents.  It is meant for those new to Visual Studio and/or working with Microsoft SQL Server.  It is not a guide to building SQL Server database connections in your code.  This is mo…
Wouldn’t it be nice if you could test whether an element is contained in an array by using a Contains method just like the one available on List objects? Wouldn’t it be good if you could write code like this? (CODE) In .NET 3.5, this is possible…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
With Secure Portal Encryption, the recipient is sent a link to their email address directing them to the email laundry delivery page. From there, the recipient will be required to enter a user name and password to enter the page. Once the recipient …

809 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question