2011-10-30 15 views
1

シーングラフを整理します。 私は、一般的なクラスのSceneNodeを持っている:C#保護されたフィールドへのアクセス

public class SceneNode 
{ 
    protected SceneNode prev, next; 
    protected SceneNodeContainer parent; 

    public SceneNode Parent { get { return parent; } } 
    public SceneNode PreviousNode { get { return prev; } } 
    public SceneNode NextNode { get { return next; } } 
} 

私もこのようなものですクラスSceneNodeContainerを、持っている:

public class SceneNodeContainer : SceneNode 
{ 
    SceneNode firstChild, lastChild; 

    public SceneNode FirstChild { get { return firstChild; } } 
    public SceneNode LastChild { get { return lastChild; } } 

    public void Add(SceneNode node) 
    { 
     Debug.Assert(node != null); 
     Debug.Assert(node.parent == null); 

     node.parent = this; 
     node.prev = lastChild; 
     node.next = null; 

     if (lastChild == null) 
     { 
      lastChild = node; 
      firstChild = lastChild; 
     } 
     else 
     { 
      lastChild.next = node; 
      lastChild = node; 
     } 
    } 

    public void Remove(SceneNode node) 
    { 
     Debug.Assert(node != null); 
     Debug.Assert(node.parent == this); 

     //unlink node 
     if (node.next != null) 
      node.next.prev = node.prev; 

     if (node.prev != null) 
      node.prev.next = node.next; 

     if (node == firstChild) 
      firstChild = node.next; 

     if (node == lastChild) 
      lastChild = node.prev; 

     node.parent = null; 
     node.next = null; 
     node.prev = null; 
    } 
} 

IntelliSenseがnode.parentや他の保護フィールドがSceneNodeContainerからアクセスできないことを言います。どうすればこれを克服できますか?

答えて

7

保護された動作のために、子タイプ(またはサブタイプ)であることがわかっているオブジェクトの保護されたフィールドにのみアクセスできます。したがって、nodeSceneNodeContainerの変数であれば、そのフィールドにアクセスできますが、それ以外の場合はアクセスできません。 C#4仕様のセクション3.5.3から

保護インスタンス部材は、それが宣言されたクラスのプログラムテキストの外側にアクセスされ、保護された内部インスタンスメンバーがアクセスされたとき宣言されたプログラムのプログラムテキストの外側では、宣言されたクラスから派生したクラス宣言内でアクセスが行われなければなりません。さらに、アクセスは、その派生クラス型のインスタンスまたはそれから構築されたクラス型を介して行われる必要があります。この制限により、メンバーが同じ基本クラスから継承されている場合でも、派生クラスが他の派生クラスの保護されたメンバーにアクセスできなくなります。

(余談として、私は個人的に、私はほとんどすべての場合で、民間非定数フィールド作る。とにかく保護されたフィールドを避けると思います。)

+0

"ほとんどの場合、非定数フィールドを非公開にします。" - あなたはデザインが貧弱であるか、または個人的な好みの症状であると考えていますか? –

+0

@ウィリアム:デザイン。フィールドは実装の詳細であり、公開されたAPIの一部であってはなりません。 –

+0

これは通常、私と一緒に起こるので、ソリューションはこの質問を投稿した直後に表示されます。 SceneNodeクラスにはAddAfterメソッドとAddBeforeメソッドが追加され、SceneNodeContainerには空のSceneNodeが最初の子として追加されます(ヘッダーリストのようになります)。そして私はフィールドを隠すことに同意します。私はそれらを基本構造体でのみ開きます。 – lazychaser

2

使用protected internalの代わりprotected、あなたはのサブのクラスからアクセスすることができます同じアセンブリ。

public class SceneNode 
{ 
    protected internal SceneNode prev, next; 
    protected internal SceneNodeContainer parent; 

    public SceneNode Parent { get { return parent; } } 
    public SceneNode PreviousNode { get { return prev; } } 
    public SceneNode NextNode { get { return next; } } 
} 
+1

'protected internal'は、同じアセンブリ内の*すべてのクラスにアクセスできます*他のアセンブリからのサブクラスは保護されている場合と同じアクセスを得ます...あなたの提案は多少ですそれを内部にすることと同じです。 (そういうわけでそれがここで働いているのです)個人的に私はプライベートフィールドにこだわっています。 –

+0

@JonSkeetはそれを手に入れました。ありがとう – Damith