62

次のコード例がある場合:

public class ClassBase
{
    public int ID { get; set; }

    public string Name { get; set; }
}

public class ClassA : ClassBase
{
    public int JustNumber { get; set; }

    public ClassA()
    {
        this.ID = 0;
        this.Name = string.Empty;
        this.JustNumber = string.Empty;
    }
}

Name変更せずにプロパティ(ClassAメンバーのメンバーとして表示されない)を非表示にするにはどうすればよいClassBaseですか?

4

10 に答える 10

86

ここでコードの匂いがします。基本クラスのすべての機能を実装している場合にのみ、基本クラスを継承する必要があるというのが私の意見です。あなたがしていることは、実際にはオブジェクト指向の原則を適切に表していません。したがって、ベースから継承したい場合は、 Name を実装する必要があります。そうしないと、継承が間違った方法で行われます。クラス A は基本クラスである必要があり、現在の基本クラスは A から継承する必要があります。それが必要な場合は、その逆ではありません。

ただし、直接の質問から離れすぎないようにしてください。「ルール」を無視して、選択したパスを続行したい場合は、次の方法で実行できます。

慣例では、プロパティを実装しますが、そのプロパティが呼び出されたときに NotImplementedException をスローしますが、それも好きではありません。しかし、それは私の個人的な意見であり、この慣習がまだ有効であることに変わりはありません。

プロパティを廃止しようとしている (そしてそれが基本クラスで仮想として宣言されている) 場合は、 Obsolete 属性を使用できます。

[Obsolete("This property has been deprecated and should no longer be used.", true)]
public override string Name 
{ 
    get 
    { 
        return base.Name; 
    }
    set
    {
        base.Name = value;
    }
}

(編集: Brian がコメントで指摘したように、属性の 2 番目のパラメーターは、誰かが Name プロパティを参照するとコンパイラ エラーを引き起こすため、派生クラスで実装したとしても、それを使用することはできません。 )

または、私が述べたように、NotImplementedException を使用します。

public override string Name
{
    get
    {
        throw new NotImplementedException();
    }
    set
    {
        throw new NotImplementedException();
    }
}

ただし、プロパティが virtual として宣言されていない場合は、 new キーワードを使用して置き換えることができます。

public new string Name
{
    get
    {
        throw new NotImplementedException();
    }
    set
    {
        throw new NotImplementedException();
    }
}

メソッドがオーバーライドされた場合と同じ方法で Obsolete 属性を引き続き使用することも、NotImplementedException をスローすることもできます。私はおそらく使用します:

[Obsolete("Don't use this", true)]
public override string Name { get; set; }

また:

[Obsolete("Don't use this", true)]
public new string Name { get; set; }

基本クラスで仮想として宣言されているかどうかによって異なります。

于 2009-12-09T17:18:04.170 に答える
42

技術的にはプロパティが非表示になることはありませんが、その使用を強く思いとどまらせる 1 つの方法は、次のように属性を設定することです。

[Browsable(false)]
[Bindable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[EditorBrowsable(EditorBrowsableState.Never)]

これは、適合しないプロパティを持つコントロールに対して System.Windows.Forms が行うことです。たとえば、Textプロパティは Control にありますが、Control から継承するすべてのクラスでは意味がありません。たとえば、MonthCalendarでは、 Text プロパティは次のように表示されます (オンライン参照ソースによる)。

[Browsable(false),
    EditorBrowsable(EditorBrowsableState.Never),
    Bindable(false), 
    DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public override string Text {
    get { return base.Text; }
    set { base.Text = value; }
}
  • ブラウズ可能- メンバーが [プロパティ] ウィンドウに表示されるかどうか
  • EditorBrowsable - メンバーが Intellisense ドロップダウンに表示されるかどうか

EditorBrowsable(false) によってプロパティの入力が妨げられることはなく、プロパティを使用してもプロジェクトはコンパイルされます。ただし、このプロパティは Intellisense に表示されないため、使用できるかどうかは明らかではありません。

于 2009-12-09T18:01:29.200 に答える
31

隠すだけ

 public class ClassBase
{
    public int ID { get; set; }
    public string Name { get; set; }
}
public class ClassA : ClassBase
{
    public int JustNumber { get; set; }
    private new string Name { get { return base.Name; } set { base.Name = value; } }
    public ClassA()
    {
        this.ID = 0;
        this.Name = string.Empty;
        this.JustNumber = 0;
    }
}

注: 基本クラスを変更しないという制約があるため、Name は ClassBase の public メンバーのままです。それを止める方法はありません。

于 2011-02-03T23:21:32.180 に答える
6

必要がないのになぜ継承を強制するのですか? それを行う適切な方法は、 is- a の代わりにhas-aを実行することだと思います。

public class ClassBase
{
    public int ID { get; set; }

    public string Name { get; set; }
}

public class ClassA
{
    private ClassBase _base;

    public int ID { get { return this._base.ID; } }

    public string JustNumber { get; set; }

    public ClassA()
    {
        this._base = new ClassBase();
        this._base.ID = 0;
        this._base.Name = string.Empty;
        this.JustNumber = string.Empty;
    }
}
于 2012-06-27T13:36:47.750 に答える
3

ここで返信する人の多くは、相続をまったく理解していないと思います。基本クラスから継承し、かつてのパブリック変数と関数を非表示にする必要があります。たとえば、基本的なエンジンがあり、過給された新しいエンジンを作成したいとします。使用するエンジンの99%ですが、機能を少し調整して実行を大幅に改善します。それでも、エンドユーザーではなく、行った変更にのみ表示する必要のある機能がいくつかあります。MSが出すすべてのクラスは、実際には変更を必要としないことは誰もが知っているからです。

新しい機能を使用して機能を単純にオーバーライドすることに加えて、Microsoftが無限の知恵を持っていることの1つです…..ああ、私は間違いがもはや価値のないツールと見なされたことを意味します。

これを実現するための最良の方法は、マルチレベルの継承です。

public class classA 
{
}

public class B : A 
{} 

public class C : B 
{} 

クラスBはすべての作業を行い、クラスCは必要なものを公開します。

于 2012-10-04T20:47:29.583 に答える
2

できません。それが継承の要点です。サブクラスは、基本クラスのすべてのメソッドとプロパティを提供する必要があります。

プロパティが呼び出されたときに例外をスローするように実装を変更できます(仮想の場合)...

于 2009-12-09T17:17:14.257 に答える
2

基本クラスからプロパティを削除してはならないことに完全に同意しますが、派生クラスには値を入力する別のより適切な方法がある場合があります。たとえば、私の場合、ItemsControl から継承しています。ご存知のように、ItemsControl には ItemsSource プロパティがありますが、コントロールに 2 つのソース (Person と Location など) からのデータをマージしたいと考えています。ユーザーに ItemsSource を使用してデータを入力させる場合、値を分離してから再結合する必要があるため、データを入力するための 2 つのプロパティを作成しました。しかし、元の質問に戻ると、これにより ItemsSource が残ります。これは、ユーザーが自分のプロパティで「置き換え」ているため、ユーザーに使用してほしくないものです。私は Browsable と EditorBrowsable のアイデアが好きですが、それでもユーザーがそれを使用することを妨げるものではありません。

于 2016-11-18T19:43:06.070 に答える
0

質問が古いことは知っていますが、できることは、次のように PostFilterProperties をオーバーライドすることです。

 protected override void PostFilterProperties(System.Collections.IDictionary properties)
    {
        properties.Remove("AccessibleDescription");
        properties.Remove("AccessibleName");
        properties.Remove("AccessibleRole");
        properties.Remove("BackgroundImage");
        properties.Remove("BackgroundImageLayout");
        properties.Remove("BorderStyle");
        properties.Remove("Cursor");
        properties.Remove("RightToLeft");
        properties.Remove("UseWaitCursor");
        properties.Remove("AllowDrop");
        properties.Remove("AutoValidate");
        properties.Remove("ContextMenuStrip");
        properties.Remove("Enabled");
        properties.Remove("ImeMode");
        //properties.Remove("TabIndex"); // Don't remove this one or the designer will break
        properties.Remove("TabStop");
        //properties.Remove("Visible");
        properties.Remove("ApplicationSettings");
        properties.Remove("DataBindings");
        properties.Remove("Tag");
        properties.Remove("GenerateMember");
        properties.Remove("Locked");
        //properties.Remove("Modifiers");
        properties.Remove("CausesValidation");
        properties.Remove("Anchor");
        properties.Remove("AutoSize");
        properties.Remove("AutoSizeMode");
        //properties.Remove("Location");
        properties.Remove("Dock");
        properties.Remove("Margin");
        properties.Remove("MaximumSize");
        properties.Remove("MinimumSize");
        properties.Remove("Padding");
        //properties.Remove("Size");
        properties.Remove("DockPadding");
        properties.Remove("AutoScrollMargin");
        properties.Remove("AutoScrollMinSize");
        properties.Remove("AutoScroll");
        properties.Remove("ForeColor");
        //properties.Remove("BackColor");
        properties.Remove("Text");
        //properties.Remove("Font");
    }
于 2015-06-14T16:51:44.697 に答える