3

私は最近c#の学習を開始し、問題に遭遇しました。私はabstract/interfaceクラスにあまり精通していませんが、基本的な原則とアプリケーションを理解しています。

私は現在、C#のOOPを検討しています。これは、Javaで実行したことのある、OOPの仕組みをすでに知っていますが、抽象クラスやインターフェイスクラスも使用したことがありません。

私のコードの目的は、オブジェクトのArrayList(共通の親クラスの両方の子)を渡し、その特定のクラスのオブジェクトのみを出力することです。これは機能しますが、親クラスが抽象である場合、親クラスのすべての子オブジェクトを同じメソッドで出力できるかどうかを知りたいと思いました。

親クラス

abstract class Person
{
    protected string Name { get; set; }
    protected int Age { get; set; }

    public override string ToString() { return "Person:" + Name + ", " + this.Age; }
}

チャイルドクラス

class Student : Person
{
    private int studID { get; set; }
    private string school { get; set; }
    public Student() { }
    public Student(string name, int age, int studID, string school)
    {
        this.Name = name;
        this.Age = age;
        this.studID = studID;
        this.school = school;
    }

    public override string ToString()
    {
        string s = "Student:" + Name + ", " + Age + ", " + studID + ", " + school;
        return s;
    }
}

メソッド呼び出し

    private static void StudentDetails(object type)
    {
        ArrayList tmp = new ArrayList();
            //display all
            //foreach (Person p in people) tmp.Add(p);
            foreach (Person p in people)
            {
                if (type.GetType() == p.GetType())
                {
                    tmp.Add(p);
                }
            }
            //etc...
4

6 に答える 6

1

GetType()は継承などをチェックしないため、比較しないでください。IsAssignableFromメソッド-> http://msdn.microsoft.com/de-de/library/system.type.isassignablefrom.aspxを確認してください。これが、探しているものです。

于 2012-06-27T12:20:44.520 に答える
1

コンパイル時にタイプがわかっている場合は、次を使用できます。

private static void StudentDetails<T>()
{
    ArrayList tmp = new ArrayList();
    foreach (Person p in people)
    {
        if (p is T)
        {
            tmp.Add(p);
        }
    }            
}

そして電話

StudentDetails<Student>();

いくつかの考え:

  1. ArrayListのように、より強く型付けされたものに変更する必要がありますList<T>。あなたの場合List<Person>

  2. StudentDetailsより良い命名をしてください。メソッド名は動詞である必要があります。

于 2012-06-27T12:23:06.390 に答える
1

コンパイル時にタイプがわかっている場合は、次のように実行できます。

var students = people.OfType<Student>().ToList();

そして、メソッドを完全に取り除きStudentDetailsます。OfType<T>ドキュメントはここにあります。

T手元にあるかどうかはわかりませんが、これはから派生した型(私の例ではから派生)も取得する可能性がありますStudent。呼び出しは、ではなくToList()が必要な場合にのみ必要です。List<T>IEnumerable<T>

引数が実行時に決定される場合、ジェネリックはこのようにコーディングする型のコンパイル時の解決を必要とするためType、このソリューションは機能しません。

于 2012-06-27T12:29:53.150 に答える
0

あなたができることは次のようなものかもしれません:

すべてのオブジェクトは抽象クラスから派生しているため、を使用しないでくださいArrayList。ただし、この場合は使用してください。IEnumerable<Person>Person

private static void StudentDetails(Type filter)
{
   var filteredTypes = people.Where(p=>p.GetType() == filter);               
    ....
}
于 2012-06-27T12:20:37.967 に答える
0

基本クラスを使用してこれをうまく行うことができます(抽象的ですが):

class Program
{
    static void Main(string[] args)
    {
        List<Person> persons = new List<Person>();

        persons.Add(new Student("John", 18, 1, "Stanford"));
        persons.Add(new Student("Matt", 20, 2, "Stanford"));
        persons.Add(new Teacher("Alice", 30));

        StudentDetails(persons);
    }

    private static void StudentDetails(List<Person> people)
    {
        foreach (Person p in people)
        {
            try
            {
                Student s = (Student)p;
                Console.WriteLine(s.ToString());
            }
            catch(InvalidCastException e)
            {
            }
        }
    }
}
于 2012-06-27T12:31:34.857 に答える
-1

初めに:

InterfaceクラスとAbstractクラスの主な違いは、ベースにメソッドを記述して、コードのデフォルトの動作を提供できることです。知られているように、ここではメソッドシグネチャのみを提供するため、インターフェイスでは不可能です。

提供したサンプルは少し疑わしいものです。そのような実装では、実際には単純な基本クラスを使用し、抽象クラスは使用しません。ベースタイプのコレクションまたはフィールドを提供するには、インスタンス化できるベースを使用する必要があります。これは、抽象クラスでは許可されていません。

今あなたの質問:

それが谷だと考えましょう。インスタンス化できないベースオブジェクトが必要ですが、このクラスのコレクションを提供したいのですが...問題が発生します。本当にこれを実行したい場合は、多くのキャストと型チェックを行う方法がありますが、この方法では、アイデア全体が意味をなしません。より良い方法はインターフェースを実装することですが、これではデフォルトの動作を提供することはできません!

私のおすすめ:

サンプルには、通常のクラスのPersonを使用し、Studentに継承させます。ベースにはデフォルトのToStringメソッドがあり、Studentクラスでオーバーライドします。将来のコードのために。次の場合に考えてください:ベースのインスタンス(コレクション、パターンなど)が必要->シンプルなベースまたはインターフェイス

デフォルトの動作とインスタンスが必要->シンプルベース

インスタンスは必要ありませんデフォルトの動作はありません->インターフェース

デフォルトの動作が必要インスタンスなし->抽象

それは、クラスの実装方法を決定する必要があるときに私がよく考えていたものです。

hth

クリストフ

于 2012-06-27T13:03:15.140 に答える