C# 如何在派生类中隐藏基类公共属性

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1443886/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 16:35:47  来源:igfitidea点击:

How can I hide a base class public property in the derived class

c#

提问by ravikiran

I want to hide the base public property(a data member) in my derived class:

我想在我的派生类中隐藏基本公共属性(数据成员):

class Program
{
    static void Main(string[] args)
    {
        b obj = new b();
        obj.item1 = 4;// should show an error but it doent ???
    }
}

class a
{
    public int item1 {get; set;}
    public int item2 { get; set; }
}

class b : a
{
    new private int item1;
}

class c : a
{

}

i have member as public because i want the member to be inherited in c class , but want to hide the member in b class , how can i do this ?

我有一个 public 成员,因为我希望成员在 c 类中被继承,但想隐藏 b 类中的成员,我该怎么做?

dont i have an option to selectively inherite the variable i want in my base class ??? thats really bad , i think ms should provide us with an option (may be a modifier) to perform this

我没有选择在我的基类中选择性地继承我想要的变量吗???那真的很糟糕,我认为 ms 应该为我们提供一个选项(可能是一个修饰符)来执行此操作



Edit:

编辑:

I found the answer myself (i heard lots of them telling this is not possible in c#, but you can kind of do it)

我自己找到了答案(我听到很多人说这在 c# 中是不可能的,但你可以这样做)

I am including the code in case it is useful

我包括代码以防它有用

class Program
{
    static void Main(string[] args)
    {
        b obj = new b();
        obj.item1 = 4; // shows an error  : )
    }
}

class a
{
    public int item1 { get; set; }
    public int item2 { get; set; }
}

class b : a
{
    new public static int item1
    {
        get;
        private set;
    }
}

回答by Henk Holterman

What you want to do goes directly against the grain of OO, you can't 'unpublish' members as this violates the substitution principle. You have to refactor this into something else.

您想要做的事情直接违背了 OO 的原则,您不能“取消发布”成员,因为这违反了替换原则。您必须将其重构为其他内容。

回答by Jason

What you are describing is something akin to 'private inheritance' from C++, and is not available in C#.

您所描述的内容类似于 C++ 中的“私有继承”,并且在 C# 中不可用。

回答by Vadim

The only thing I can think of is to make item1 virtual in class a:

我唯一能想到的就是在 a 类中将 item1 设为虚拟:

class a
{
    public virtual int item1 { get; set; }
    public int item2 { get; set; }

}

and then override it in class b but throw an exception in getter and setter. Also if this property is used in a visual designer you can use Browsable attributeto not display.

然后在 b 类中覆盖它,但在 getter 和 setter 中抛出异常。此外,如果在可视化设计器中使用此属性,您可以使用Browsable 属性不显示。

class b : a
{
    [Browsable(false)]
    public override int item1
    {
        get
        {
            throw new NotSupportedException();
        }
        set
        {
            throw new NotSupportedException();
        }
    }
}

回答by JDunkerley

You cant do it directly, but you could override the properties in the child class and make them readonly e.g.

你不能直接做,但你可以覆盖子类中的属性并使它们只读,例如

class Program
{
    static void Main(string[] args)
    {
        b obj = new b();
        obj.item1 = 4;// should show an error but it doent ???
    }
}

class a
{
    public virtual int item1 {get; set;}
    public virtual int item2 { get; set; }

}

class b : a
{
    public override int item1
    { 
         get { return base.item1; }
         set { }
    }
}

    class c : a
{

}

回答by BeerHugger

You could use interfaces to hide the property. The child class would implemented an interface that didn't have the property then it wouldn't appear.

您可以使用接口来隐藏该属性。子类将实现一个没有属性的接口,然后它就不会出现。

You would need two interfaces for when you want the property and when you don't, thus making it a horrible hack.

您需要两个接口,分别用于何时需要该属性和何时不需要该属性,从而使其成为一个可怕的黑客。

回答by ICR

I'm going to attempt to explain with examples why this is a bad idea, rather than using cryptic terms.

我将尝试用例子来解释为什么这是一个坏主意,而不是使用神秘的术语。

Your proposal would be to have code that looks like this:

您的建议是使用如下所示的代码:

public class Base
{
    public int Item1 { get; set; }
    public int Item2 { get; set; }
}


public class WithHidden : Base
{
    hide Item1; // Assuming some new feature "hide" in C#
}

public class WithoutHidden : Base { }

This would then make the following code invalid:

这将使以下代码无效:

WithHidden a = new WithHidden();
a.Item1 = 10; // Invalid - cannot access property Item1
int i = a.Item1; // Invalid - cannot access property Item1

And that would be just what you wanted. However, suppose we now have the following code:

而这正是你想要的。但是,假设我们现在有以下代码:

Base withHidden = new WithHidden();
Base withoutHidden = new WithoutHidden();

SetItem1(withHidden);
SetItem1(withoutHidden);

public void SetItem1(Base base)
{
    base.Item1 = 10;
}

The compiler doesn't know what runtime type the argument base in SetItem1 will be, only that it is at least of type Base (or some type derived from Base, but it can't tell which -- it may be obvious looking at the code snippet, but more complex scenarios make it practically impossible).

编译器不知道 SetItem1 中的参数 base 将是什么运行时类型,只知道它至少是 Base 类型(或从 Base 派生的某种类型,但它无法分辨是哪种类型——查看代码片段,但更复杂的场景使其几乎不可能)。

So the compiler will not, in a large percentage of the cases, be able to give a compiler error that Item1 is in fact inaccessible. So that leaves the possibility of a runtime check. When you try and set Item1 on an object which is in fact of type WithHidden it would throw an exception.

因此,在大部分情况下,编译器将无法给出 Item1 实际上无法访问的编译器错误。所以这就留下了运行时检查的可能性。当您尝试在实际上是 WithHidden 类型的对象上设置 Item1 时,它会引发异常。

Now accessing any member, any property on any non-sealed class (which is most of them) may throw an exception because it was actually a derived class which hid the member. Any library which exposes any non-sealed types would have to write defensive code when accessing anymember just because someone may have hidden it.

现在访问任何成员,任何非密封类(大多数)上的任何属性都可能引发异常,因为它实际上是隐藏该成员的派生类。任何暴露任何非密封类型的库在访问任何成员时都必须编写防御性代码,因为有人可能隐藏了它。

A potential solution to this is to write the feature such that only members which declare themselves hideable can be hidden. The compiler would then disallow any access to the hidden member on variables of that type (compile time), and also include runtime checks so that a FieldAccessException is thrown if it is cast to the base type and tried to be accessed from that (runtime).

一个潜在的解决方案是编写该功能,以便只有声明自己可隐藏的成员才能隐藏。然后,编译器将禁止对该类型变量的任何隐藏成员的访问(编译时),并且还包括运行时检查,以便在将 FieldAccessException 强制转换为基类型并尝试从中访问(运行时)时抛出 FieldAccessException .

But even if the C# developers did go to the huge trouble and expense of this feature (remember, features are expensive, especially in language design) defensive code still has to be written to avoid the problems of potential FieldAccessExceptions being thrown, so what advantage over reorganising your inheritance hierarchy have you gained? With the new member hiding feature there would be a huge number of potential places for bugs to creep into your application and libraries, increasing development and testing time.

但是即使 C# 开发人员确实为此功能付出了巨大的麻烦和费用(记住,功能是昂贵的,尤其是在语言设计中)仍然需要编写防御性代码来避免抛出潜在的 FieldAccessExceptions 的问题,那么有什么优势呢?重组您的继承层次结构您获得了吗?使用新的成员隐藏功能,将有大量潜在的错误可以潜入您的应用程序和库,从而增加开发和测试时间。

回答by ICR

Vadim's response reminded me of how MS achieve this in the Framework in certain places. The general strategy is to hide the member from Intellisense using the EditorBrowsable attribute. (N.B. This only hides it if it is in another assembly) Whilst it does not stop anyone from using the attribute, and they can see it if they cast to the base type (see my previous explination) it makes it far less discoverable as it doesn't appear in Intellisense and keeps the interface of the class clean.

Vadim 的回应让我想起了 MS 如何在某些地方的框架中实现这一点。一般策略是使用EditorBrowsable 属性对Intellisense 隐藏成员。(注意,如果它在另一个程序集中,这只会隐藏它)虽然它不会阻止任何人使用该属性,并且如果他们转换为基本类型,他们可以看到它(请参阅我之前的解释)它使它更不容易被发现不会出现在 Intellisense 中并保持类的界面干净。

It should be used sparingly though, only when other options like restructuring the inheritance hierarchy would make it a lotmore complex. It's a last resort rather than the first solution to think of.

它应该谨慎,虽然可以使用,只有当像重组继承层次其他选项将使其成为很多更加复杂。这是最后的手段,而不是第一个想到的解决方案。

回答by Abhishek Panchal

namespace PropertyTest    
{    
    class a
    {    
        int nVal;

        public virtual int PropVal
        {
            get
            {
                return nVal;
            }
            set
            {
                nVal = value;
            }
        }
    }

    class b : a
    {
        public new int PropVal
        {
            get
            {
                return base.PropVal;
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            a objA = new a();
            objA.PropVal = 1;

            Console.WriteLine(objA.PropVal);

            b objB = new b();
            objB.PropVal = 10; // ERROR! Can't set PropVal using B class obj. 
            Console.Read();
        }
    }
}

回答by pingsft

You can override it and then Add a [Browsable(false)] tag to prevent showing it in designer.

您可以覆盖它,然后添加 [Browsable(false)] 标签以防止在设计器中显示它。

Simple:

简单的:

public class a:TextBox
{
        [Browsable(false)]
        public override string Text
        {
            get { return ""; }
            set { }
        }
}

回答by Paul Turner

Changing the accessibility of a virtual member is an inheriting class is specifically prohibited by the C# language spec:

更改虚拟成员的可访问性是 C# 语言规范明确禁止的继承类:

The override declaration and the overridden base method have the same declared accessibility. In other words, an override declaration cannot change the accessibility of the virtual method.However, if the overridden base method is protected internal and it is declared in a different assembly than the assembly containing the override method then the override method's declared accessibility must be protected.

覆盖声明和覆盖的基方法具有相同的声明可访问性。换句话说,覆盖声明不能改变虚方法的可访问性。但是,如果重写的基方法是受保护的内部方法,并且它是在与包含重写方法的程序集不同的程序集中声明的,则必须保护重写方法声明的可访问性。

From section 10.6.4 Override methods

来自 10.6.4 节覆盖方法

The same rules which apply to overriding method also apply to properties, so going from publicto privateby inheriting from the base class can't be done in C#.

这适用于重载方法相同的规则也适用于性能,从这么去publicprivate从基类继承不能在C#来完成。