Frage

Hello stackoverflow community!

Let's start!

I have one small class Person:

class Person
{
    public string name { get; set; }
}

Аnd it has a descendant Employee:

class Employee : Person
{
    public int salary { get; set; }
}

And second descendant is Guest:

class Guest: Person
{
    public int id { get; set; }
}

Ok! looks good :)

Now I want to display a list of all employees OR guests in a single control ListView

I made a class (it really necessary) for list management PeopleList:

class PeopleList
{
    public List<Person> People { get; set; }

    ...

    public void LoadListFromFile()
    {
        // Load logic

        this.People = new List<?>(source);
    }
}

Do you see this question mark? No? Look at the code again!

How to create an instance of List that I can use my class something like this:

// This instance with the list of Person objects
PeopleList list = new PeopleList();

foreach (Employee e in list.People)
{
    Debug.WriteLine(e.salary.toString());
}

// This instance with the list of Guest objects
PeopleList list = new PeopleList();

foreach (Guest g in list.People)
{
    Debug.WriteLine(g.id.toString());
}

P.S. I'm new in c# and I think that I have a problem in architecture. And maybe you point me to the pattern solves my problem. I really need your help! Thank you!

War es hilfreich?

Lösung

I think you're after OfType, in the System.Linq library:

foreach (Employee e in personList.OfType<Employee>())
{
    Debug.WriteLine(e.salary.toString());
}
foreach (Guest g in personList.OfType<Guest>())
{
    Debug.WriteLine(g.id.toString());
}

Andere Tipps

The only field in Person that is shared with all of the decedents is the field 'name', therefore, if you are casting each item in your list to Person you will only have access to 'name'.

You have a few options to solve this issue. 1) you could move all of the common fields into the base class, but this is probably not want since it defeats the point of an object hierarchy, or 2) you can type check, using the "Is" keyword, each person in the list so see what type of person it is and then cast that Person to the appropriate decedent class before you operate on it.

For example:

foreach (Person p in list.People)
{
    if(p is Employee)
    {
      Debug.WriteLine(((Employee)p).salary.toString());
    }

    if(p is Guest)
    {
      Debug.WriteLine(((Guest)p).Id.toString());
    }
}

Here is an alternate more clear way of casting

foreach (Person p in list.People)
{
    if(p is Employee)
    {
      Employee employee = p as Employee;

      Debug.WriteLine(employee.salary.toString());
    }

    if(p is Guest)
    {
      Guest guest = p as Guest;     

      Debug.WriteLine(guest.Id.toString());
    }

}

Additionally you can learn more about type checking using the "is" keyword here.

Also just for clarity, since it might not be obvious, some others have suggested that you use OfType in linq but this more of a way to filter like object from a list of mixed objects as opposed to actually type checking each one.

Enjoy!

As the comments are saying, you can do the following;

public void LoadListFromFile()
{
    // Load logic

    this.People = new List<Person>(source);
}

And then, cast where appropriate;

foreach (Person e in list.People.Where(p => p.GetType() == typeof(Employee)))
{
    Debug.WriteLine(((Employee)e).salary.toString());
}

I think in your particular example, the inheritance structure is not adding much benefit, but I digress.

In your example, the easiest solution would be to override the ToString method in each one of your classes.

Having to know the exact type of the object before hand before you run some sort of calculation or display puts the onus of that calculation onto the calling code, if you make a 3rd type, you would have to update all possible references, giving you a maintenance nightmare.

The feel the logic of how to represent itself should be the responsibility (in your example) of the object itself.

This is what overriding ToString gives you, the responsibility of representing itself is then given to the thing that knows best (the object you're asking).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top