Solved

C#: Object Oriented issue

Posted on 2010-09-07
26
429 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
Comment Utility
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
Comment Utility
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
Comment Utility
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
 
LVL 29

Expert Comment

by:anarki_jimbel
Comment Utility
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
Comment Utility
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
Comment Utility
@karelog - define your requirement precisely.
0
 

Author Comment

by:karelog
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 

Author Comment

by:karelog
Comment Utility
@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
Comment Utility
What do you mean?
0
 

Author Comment

by:karelog
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
@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
Comment Utility
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
Comment Utility
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
Comment Utility
@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
Comment Utility
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
Comment Utility
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
Comment Utility
Excelent!

I am pleased that you found the answer.

That code is fine :)
0
 

Author Closing Comment

by:karelog
Comment Utility
Thanks everybody for helping me with this ^^
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Suggested Solutions

Introduction Hi all and welcome to my first article on Experts Exchange. A while ago, someone asked me if i could do some tutorials on object oriented programming. I decided to do them on C#. Now you may ask me, why's that? Well, one of the re…
Have you tried to learn about Unicode, UTF-8, and multibyte text encoding and all the articles are just too "academic" or too technical? This article aims to make the whole topic easy for just about anyone to understand.
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.
Access reports are powerful and flexible. Learn how to create a query and then a grouped report using the wizard. Modify the report design after the wizard is done to make it look better. There will be another video to explain how to put the final p…

763 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

Need Help in Real-Time?

Connect with top rated Experts

6 Experts available now in Live!

Get 1:1 Help Now