1

次の方法を検討してください。

public PrintObjectHierarchy(object o)
{
   Console.WriteLine(o.GetType.FullName);

   object baseObject = PruneObjectToItsBaseObject(o);
   if(!baseObject.GetType().Equals(typeof(object)))
       PrintObjectHierarchy(baseObject);
   else Console.WriteLine("System.Object");
}

たとえば、私が書いた場合:

class Form1 : Form
{
  static void Main()
  {
    Form1 f1 = new Form1();
    PrintObjectHierarchy(f1);
  }
}

次に、私のために印刷する必要があります:

MyNamespace.Form1
System.Windows.Form
System.Windows.Forms.ContainerControl
/*and so so till...*/
System.Object

残念ながら、オブジェクトをその BaseType に CAST したとしても、「C# ポリモーフィズム」はそのVIEWを基本型に制限するだけで、 REALベース オブジェクトからREAL参照を返してくれません! 例を挙げて説明しましょう。私が持っている場合

class Person {
public string Name;
public string LastName;
}
class President : Person {
public string password;
}

main(){
President pr = new President() {Name="John"; LastName="Smith"; password="js123" };
Person p = (Person)pr;
SendToAirportSystemAcrossInternet(p);
}

pだと思いますが、そうではありません! それは大統領であり、pはそこからの眺めにすぎないため、大統領のパスワードはインターネット上を移動します。

オブジェクトをプルーニングまたはスライスして、実際のベース オブジェクトを作成する方法についてのアイデアはありますか?

前もって感謝します!

4

4 に答える 4

2

ダニエルの解決策は機能します。別の同様のアプローチは、「コピーコンストラクター」を作成し、その方法で新しい人を作成することです。

したがって、個人クラスは次のようになります。

public class Person
{
    public Person()
    {
    }

    public Person(Person p)
    {
        this.name = p.name;
        this.lastName = p.lastName
    }

    public string name;
    public string lastName;
}

そして、あなたはこのような大統領から人を作ることができます:

President pres = new President() { name = "abc", lastName = "def", password = "kittens" };
Person p = new Person(pres);

これにより、大統領から人が作成されますが、大統領に戻る方法も、パスワードを取得する方法もありません。これが人を作って大統領にキャストすると、あなたはそれを手に入れるでしょうInvalidCastException、それはあなたが望むものだと思います。

于 2012-05-09T10:34:55.150 に答える
2

何を達成しようとしているのかは明らかではありませんが、オブジェクトの継承階層に関心があるため、 のインスタンスを処理したいと思うでしょうSystem.Type。これは、投稿した最初の方法の実用的なバージョンであり、そこから先に進む方法についてのヒントが得られる可能性があります。

static void PrintObjectHierarchy(object o)
{
    Type t = o.GetType();
    while (t != null)
    {
        Console.WriteLine(t.FullName);
        t = t.BaseType;
    }
}
于 2012-05-09T10:59:13.490 に答える
1

基本的に、やりたいことはできません。この要件がないように再設計する必要があります。

コメントで指摘したように、基本クラスの一連のフィールドは、実行時の型が派生クラスの場合は有効ですが、そのクラスのインスタンスだけでは無効である可能性があります。さらに、オブジェクトがこのように表示されたときに単に無効になる、あらゆる種類の他のセーフガードが存在する可能性があります。たとえば、基本クラスは値のコレクションへの参照を保持し、派生クラスはそのコレクションに追加された値を検証することが期待されます。オブジェクトが「プルーニング」されると、その検証は削除されますが、以前と同じコレクションへの参照が含まれます。

// EvenNumbersOnlyCollection rejects odd numbers
EvenNumberCollection derived = new EvenNumbersOnlyCollection();
NumberCollection pruned = Prune<NumberCollection>(derived);
pruned.Add(5);

// This would return 5 - the invariant is broken!
int shouldBeEven = derived.First();

この刈り込みが良いアイデアだと思う理由は明らかではありませんが、他の方法でより広い目標を達成するように努めるべきです。

于 2012-05-09T15:59:54.113 に答える
0

オブジェクトが C# で作成されると、常に元の型にキャストされます。ベース オブジェクトまたはインターフェイスとして使用している場合でも、呼び出し p.GetType() は常に元の型を返します。

新しいオブジェクトを作成する必要があり、そのベース オブジェクトにプルーニングする必要がある場合は、タイプの新しいオブジェクトを作成する必要があります。例えば:

public class ParentClass
{
  public Parent(int feature1)
  {
    mFeature1 = feature1;
  }
}

public class ChildClass : ParentClass
{
  public ChildClass(int feature1, int feature2) : base(feature1)
  {
    mFeature2 = feature2;
  }
}

...
...
ChildClass cc = new ChildClass(10, 20);
ParentClass pc = (ParentClass)cc; // pc still is of type ChildClass
ParentClass ccAsParent = new ParentClass(cc.Feature1); //ccAsParent is of type ParentClass
...
...

親クラスがabstractでない場合にのみこれを行うことができることに注意してください。

于 2012-05-09T10:27:12.020 に答える