如果我有以下代码示例:

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 (不显示为A类成员)无需修改 ClassBase ?

有帮助吗?

解决方案

我在这里闻到了代码的味道。我认为,只有在实现基类的所有功能时才应该继承该基类。您所做的并没有真正正确地代表面向对象的原则。因此,如果你想从你的基础继承,你应该实现 Name,否则你的继承方式是错误的。你的类 A 应该是你的基类,如果你想要的话,你当前的基类应该继承自 A,而不是相反。

然而, 不要偏离直接问题太远。如果你 做过 想要藐视“规则”并想要继续走你选择的道路 - 以下是你可以采取的方法:

约定是实现该属性,但在调用该属性时抛出 NotImplementedException - 尽管我也不喜欢这样。但这是我个人的观点,并不能改变这个惯例仍然有效的事实。

如果您尝试废弃该属性(并且在基类中将其声明为 virtual),那么您可以对其使用 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 在评论中指出的那样,如果有人引用 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; }

取决于它是否在基类中声明为虚拟的。

其他提示

虽然从技术上讲,该属性不会被隐藏,但强烈阻止其使用的一种方法是在其上添加如下属性:

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

这就是 System.Windows.Forms 对具有不合适属性的控件所做的事情。这 文本 例如,属性位于 Control 上,但它对于从 Control 继承的每个类都没有意义。所以在 月历, 例如,Text 属性如下所示(根据在线参考源):

[Browsable(false),
    EditorBrowsable(EditorBrowsableState.Never),
    Bindable(false), 
    DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public override string Text {
    get { return base.Text; }
    set { base.Text = value; }
}
  • 可浏览 - 成员是否显示在“属性”窗口中
  • 编辑器可浏览 - 成员是否出现在智能感知下拉列表中

EditorBrowsable(false) 不会阻止您输入该属性,并且如果您使用该属性,您的项目仍将编译。但由于该属性没有出现在 Intellisense 中,因此您可以使用它不会那么明显。

只是隐藏它

 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 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;
    }
}

我完全同意不应从基类中删除属性,但有时派生类可能有不同的更合适的方法来输入值。例如,就我而言,我继承自 ItemsControl。众所周知,ItemsControl 具有 ItemsSource 属性,但我希望我的控件合并来自 2 个源(例如,人员和位置)的数据。如果我要用户使用 ItemsSource 输入数据,我需要分离然后重新组合这些值,因此我创建了 2 个属性来输入数据。但回到最初的问题,这留下了 ItemsSource,我不希望用户使用它,因为我用我自己的属性“替换”它。我喜欢 Browsable 和 EditorBrowsable 的想法,但这仍然不妨碍用户使用它。这里的基本点是继承应该保留大部分属性,但是当存在一个大型复杂类(尤其是无法修改原始代码的类)时,重写所有内容将非常低效。

我认为很多在这里回复的人根本不理解继承。需要从基类继承并隐藏其曾经的公共变量和函数。例如,假设您有一个基本发动机,并且您想要制造一个增压的新发动机。好吧,您将使用 99% 的引擎,但您将对其功能进行一些调整以使其运行得更好,但仍然有一些功能应该只向所做的修改显示,而不是向最终用户显示。因为我们都知道 MS 推出的每个类别实际上都不需要任何修改。

除了使用新功能来简单地覆盖功能之外,这是微软无限智慧的事情之一......哦,我的意思是错误被认为是不再值得的工具。

现在实现这一点的最佳方法是多级继承。

public class classA 
{
}

public class B : A 
{} 

public class C : B 
{} 

B 类完成您的所有工作,C 类公开您需要公开的内容。

你不能,这就是继承的全部意义:子类必须提供基类的所有方法和属性。

您可以更改实现以在调用属性时引发异常(如果它是虚拟的)...

我认为如果您必须这样做,那么这是糟糕的设计,特别是如果您能够从头开始设计代码。

为什么?

好的设计是让基类共享某个概念所具有的共同属性(虚拟的或真实的)。例子:C# 中的 System.IO.Stream。

再往下走,糟糕的设计将增加维护成本,并使实施变得越来越困难。尽量避免这种情况!

我使用的基本规则:

  • 尽量减少基类中属性和方法的数量。如果你不希望使用继承基类的类中的某些属性或方法;那么不要把它放在基类中。如果您正处于项目的开发阶段;总是时不时地回到绘图板检查设计,因为事情会发生变化!需要时重新设计。当您的项目上线时,设计后期更改内容的成本将会上升!

    • 如果您使用的是由第三方实现的基类,请考虑“上升”一级,而不是使用“NotImplementedException”等“覆盖”。如果没有其他级别,请考虑从头开始设计代码。

    • 始终考虑密封您不希望任何人能够继承的类。它迫使编码人员在“继承层次结构”中“上升一级”,从而可以避免像“NotImplementedException”这样的“松散的结局”。

我知道这个问题很老了,但是你可以做的是重写 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");
    }

您可以使用 Browsable(false)

[Browsable( false )]
public override string Name
{
    get { return base.Name; }
    set { base.Name= value; }
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top