2

こんにちはスタックオーバーフローコミュニティ!

はじめましょう!

私は1つの小さなクラスを持っていますPerson:

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

子孫があることEmployee:

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

そして 2 番目の子孫はGuest次のとおりです。

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

Ok!いいね :)

すべての従業員またはゲストのリストを単一のコントロールに表示したい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あなたの例では、最も簡単な解決策は、各クラスのメソッドをオーバーライドすることです。

ある種の計算または表示を実行する前に、オブジェクトの正確なタイプを事前に知っておく必要があると、その計算の責任が呼び出しコードにかかります。3 番目のタイプを作成する場合は、すべての可能な参照を更新する必要があります。メンテナンスの悪夢。

それ自体を表現する方法のロジックは、(あなたの例では) オブジェクト自体の責任である必要があります。

これがオーバーライド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 に答える