2012-01-17 15 views
11

私は、次の従業員オブジェクト(簡体字)を作成した場合...カスタムC#オブジェクトには、同じタイプのプロパティが含まれていますか?

public class Employee 
    { 
     public Employee() 
     {  
     } 

     public String StaffID { get; set; } 
     public String Forename { get; set; } 
     public String Surname { get; set; } 
    } 

...種類も従業員であることを従業員オブジェクト内の別のプロパティを持つことが許容可能であるマネージャの詳細を保持する(下記参照)

public class Employee 
    { 
     public Employee() 
     {  
     } 

     public String StaffID { get; set; } 
     public String Forename { get; set; } 
     public String Surname { get; set; } 

     public Employee Manager { get; set; } 
    } 

また、マネージャープロパティの従業員オブジェクトをインスタンス化するための最良の方法は何ですか?明らかにコンストラクタにthis.Manager = new Employee();を含めると、無限ループが発生します。 マネージャクラス従業員から継承するクラスは、すべてのプロパティが同じであっても最良の方法でしょうか?

+3

@FelixK。それは少しひどいです、その良い質問といくつかの関心を引いてこれを読んで* ..コンストラクタで無限ループ*が発生します。すべてが専門家ではないことを忘れないでください。 – V4Vendetta

+0

@ V4Vendettaそれは本当です、我々はすべての専門家ではありません。しかし、私は問題や質問がある場合、私は問題を引き起こすタスクを解決するいくつかの方法をテストするつもりです。 –

+0

@FelixK。はい、私はそれを試してみました、そしてそれはうまくコンパイルされました - これは私の質問が、それが「うまくいく」よりむしろ「受け入れられる」かどうかということでした - これは良い練習かどうかを確認したいと思いました。それが起こるにつれて、オブジェクトのインスタンス化に関する以下の解決策は、私が結論したこととほぼ同じですが、比較的経験の浅いため、私が軌道に乗っていることを確認したかったのです。 – triplestones

答えて

17

オブジェクトは、に実際には独自のオブジェクトの参照があります。

ほとんどのNodeタイプのオブジェクトが実装されています。

インスタンス化の場合、Employeeオブジェクトをマネージャとして使用して渡すことができます(マネージャがない場合はをに渡します)。コンストラクターは複数のオーバーロードを持つことができます。

public Employee(Employee manager) 
{ 
    this.Manager = manager; 
} 
+1

+1、 'Node'タイプとの比較が良いです。 – ken2k

+0

...しかし、明らかにコンストラクタのプロパティ/フィールドを無条件に初期化するべきではありません。なぜなら、オブジェクトのサイズ、割り当てられたスタックサイズ、および全体的なスタックサイズに応じて、 'StackOverflowException'または' OutOfMemoryException'を引き起こすからです。使用可能なメモリ)。 – Nuffin

+1

@Tobias上記のコードは例外を発生させません。これは、 'this.Manager = new Employee()'で初期化すると1つになります。 –

7

はい、オブジェクトには同じクラスの他のオブジェクトへの参照を含めることができます。

そして第二に、私はcunstructorに新しい従業員を作成しますが、このようにそれを注入しないでしょう。

public class Employee 
{ 
    public Employee(Employee manager) 
    { 
     this.Manager = manager; 
    } 

    public String StaffID { get; set; } 
    public String Forename { get; set; } 
    public String Surname { get; set; } 

    public Employee Manager { get; set; } 
} 
+0

+1! –

1

それは動作しますが、あなただけのs.th.を試すことができます以下のように:

public class A 
{ 
    public A test { get; set; } 
} 
2

はい、あなたはEmployee内部Employeeを持つことができ、それが無限ループを引き起こすことはありません、デフォルトでEmployeeオブジェクトのManagerプロパティがnullになります。

1

具体的には、建設の問題(私はOdeds答えを+1しました) - あなたが言うように、コンストラクタでインスタンスを作成することは悪い動きです。

しかし、あなた自身に尋ねてください。なぜあなたはとにかく必要なのでしょうか? Manager/Employeeのケースでは、従業員に常にマネージャがあることを常に確信することはできません。従業員が常にマネージャを持っていることを必ずしも確信することはできず、そうでない場合は空白のインスタンスnewを使用してnullを示すべきではありません。

プロパティでパブリックget/setアクセサを使用する場合は、通常、外部ソースからこれらのオブジェクトツリーをロードしている可能性があります。その場合は、何も心配はありません。同様に、マネージャ/従業員関係などの他のEmployeeインスタンスを受け入れるコンストラクタを使用することもできます。

また、そのコンストラクタの循環関係もチェックする必要があります。従業員は誰かのマネージャーとその従業員になれません - そのために子 - >親関係を歩き、それが終わるかどうかを見てください!

0

最初に、答えはです。オブジェクトは、自身のインスタンスを含むフィールドを持つことができます。それも、受け入れる方法を持っているか、同じクラスのインスタンスを返す、と言っても、クラスの定義の中で自分自身に依存することができ、例えばすることができます

public class Person : IComparable<Person> //legal, recursive definition 
{ 
    //fields (or properties) that are of type Person 
    public Person Father; 
    public Person Mother; 
    public List<Person> Children; 

    // method that takes a Person as a parameter 
    public bool IsParent(Person potentialParent) 
    { 
     .... 
    } 

    //method that returs a Person 
    public Person Clone() 
    { 
     //TODO: real implementation coming soon 
    } 

    public Person(){} 

    //constructor that takes persons as arguments 
    public Person(Person father, Person Mother) 
    { 
     Father = father; 
     Mother = mother; 
    } 
} 

デフォルトでは、すべての基準値はnullある「あなたのでdは自分で作成しない限り、コンストラクターに問題はありません。したがって、はいでは、循環参照と無限ループ(それぞれの親には親を持つ子を持つ子がいます...)でも問題はあるかもしれませんが、通常は簡単に検出し回避できます。私は円形に参照されるオブジェクトのシリアライズをXML(または他のテキストベース)を使用する場合

私は問題のこれらの種類に遭遇した唯一の時間があります。

3

このでない唯一のシナリオは、structです。 structが含まれる直接Employee構造体の大きさは円形である「他のフィールドのサイズを加えた従業員のサイズ」でなければならないので、(むしろデータの固定サイズの基準であるより) 。

あなたが持つことができません。特に

struct Foo { 
    Foo foo; 
} 

(または円形の大きさにつながる何か) - コンパイラがで応答:

構造体のメンバ 'Foo.foo'型 'Foo'は、構造体レイアウトのサイクルを引き起こします。

ただし、それ以外の場合はすべて問題ありません。初期化の問題で、私は言うだろう:それは最初に割り当てられていないままにして、呼び出し側がプロパティを介して値を割り当てることができます。

0

私はこの方法を試してみましたが、それが私の仕事:

class Program 
{ 
    static void Main(string[] args) 
    { 
     A a = new A(new A()); 
    } 
} 

public class A 
{ 
    public string Name { get; set; } 
    public A a; 

    public A() { } 
    public A(A _a) 
    { 
     a = _a; 
    } 
} 

今、あなたは以下のようにmain()関数でそれを使用することができます。

class Program 
{ 
    static void Main(string[] args) 
    { 
     A a = new A(new A()); 
     a.Name = "Roger"; 
     a.a.Name = "John"; 
     Console.WriteLine("{0}, {1}", a.Name, a.a.Name); 
    } 
} 
関連する問題