2

你好 stackoverflow 社区!

开始吧!

我有一个小班Person

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

Аnd 它有一个后代Employee

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

第二个后代是Guest

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

好的!看起来不错 :)

现在我想在一个控件中显示所有员工或客人的列表ListView

我为列表管理开设了一个课程(真的很有必要)PeopleList

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

    ...

    public void LoadListFromFile()
    {
        // Load logic

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

你看到这个问号了吗?不?再看代码!

如何创建一个List我可以使用我的类的实例,如下所示:

// 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());
}

PS我是c#的新手,我认为我在架构方面有问题。也许你指出我的模式可以解决我的问题。我真的需要你的帮助!谢谢!

4

4 回答 4

4

我想你在OfType图书馆System.Linq之后:

foreach (Employee e in personList.OfType<Employee>())
{
    Debug.WriteLine(e.salary.toString());
}
foreach (Guest g in personList.OfType<Guest>())
{
    Debug.WriteLine(g.id.toString());
}
于 2013-09-01T23:47:46.867 回答
1

Person 中唯一与所有死者共享的字段是“name”字段,因此,如果您将列表中的每个项目转换为 Person,您将只能访问“name”。

你有几个选项来解决这个问题。1)您可以将所有公共字段移动到基类中,但这可能是不想要的,因为它破坏了对象层次结构的点,或者 2)您可以使用“Is”关键字键入检查,每个人在列出所以查看它是什么类型的人,然后在操作之前将该人转换为适当的死者类

例如:

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());
    }
}

这是另一种更清晰的投射方式

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());
    }

}

此外,您可以在此处了解有关使用“is”关键字进行类型检查的更多信息。

也只是为了清楚起见,因为它可能不明显,其他一些人建议您在 linq 中使用 OfType 但这更多的是从混合对象列表中过滤类似对象的方法,而不是实际类型检查每个对象。

享受!

于 2013-09-01T23:36:52.613 回答
0

我认为在您的特定示例中,继承结构并没有增加太多好处,但是我离题了。

在您的示例中,最简单的解决方案是覆盖ToString每个类中的方法。

在运行某种计算或显示之前必须事先知道对象的确切类型将该计算的责任推给调用代码,如果您进行第三种类型,则必须更新所有可能的引用,给您一个维护噩梦。

感觉如何表示自己的逻辑应该是对象本身的责任(在你的例子中)。

这就是压倒一切ToString给您的,然后将代表自己的责任交给最了解的事物(您要询问的对象)。

于 2013-09-01T23:59:59.147 回答
0

正如评论所说,您可以执行以下操作;

public void LoadListFromFile()
{
    // Load logic

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

然后,在适当的地方施放;

foreach (Person e in list.People.Where(p => p.GetType() == typeof(Employee)))
{
    Debug.WriteLine(((Employee)e).salary.toString());
}
于 2013-09-01T23:40:53.147 回答