C#中的Protected关键字

23

我想了解在C#中,protected的含义是什么,我们为什么要使用它以及这个关键字的好处是什么?

例如:

protected int currentColorIndex;

请详细说明。


6
感觉这肯定是一个重复的问题,但我在 Stack Overflow 上找不到完全相同的问题。 - serg10
1
既然你已经从这些答案中掌握了基础知识,你可能想深入了解一些微妙之处。请参阅http://blogs.msdn.com/b/ericlippert/archive/tags/protected/ 了解更多信息。 - Eric Lippert
相关:https://dev59.com/sk_Ta4cB1Zd3GeqPENOB - user195488
7个回答

48

每个人的答案都很相似(定义和/或MSDN链接的摘录),所以我将尝试回答您最初的三个问题:

意义:

任何标记为'protected'的字段表示它仅对自身和任何子级(继承自它的类)可见。您会注意到在ASP.NET Web Forms代码后台模型中,事件处理程序(如Page_Load)被标记为'protected'。这是因为ASPX标记文件实际上是从代码后台文件继承而来的(查看@Page指令以证明此点)。

为什么使用它:

protected访问修饰符的常见用途是使子类能够访问其父类的属性。您可能有一个基类,许多子类从中派生。这个基类可能有一个公共属性。这是使用protected属性的好例子-为了便于重用和集中维护公共逻辑。

好处:

这与“为什么使用它?”的问题有些类似,但本质上它提供了粗粒度的属性控制。您不能仅考虑“何时使用protected”。更多的情况是选择何时使用哪种访问修饰符(private、public、internal、protected)。因此,好处实际上与任何访问修饰符的好处相同-提供健壮一致的对象模型,最大化代码重用并最小化与不正确暴露的代码相关的安全风险。

希望这可以帮助到您。


在抽象类中是否可以访问受保护的方法,还是我们需要覆盖它?例如,我有一个名为“Dad”的类,其中有一个protected void WalkingAndRunning()方法。 "Dad"类被"Son"类继承。在那里使用protected void WalkingAndRunning()方法是否可行?只是好奇。 - Musikero31
1
@Musikero31 父类中的受保护函数会自动继承到子类:Dad:Son.. 在Son类中甚至不需要列出它,除非您想更改其功能。 - Joseph Poirier
1
@JosephPoirier 在8年之后,看着我的问题以及你几乎以与我相同的方式回答我的问题,让我回想起过去和现在的自己,感到非常欣慰。我会为你的回答点赞。 - Musikero31

24

正如其他人已经指出的:

protected关键字是一种成员访问修饰符。受保护的成员可以在其类内以及由派生类实例访问。

这里是一个小例子:

public class A
{
    protected string SomeString;
    public string SomeOtherString;
}

public class B : A
{
    public string Wrapped
    {
        get { return this.SomeString; }
    }
}

...

var a = new A();
var s = a.SomeOtherString; // valid
var s2 = a.SomeString; // Error

var b = new B();
var s3 = b.Wrapped; // valid

谢谢您。您能否澄清b.SomeString是否有效?这是MSDN上没有解释的部分。 - David Tang
2
@Box9,b.SomeString不合法,因为它是protectedprotected基本上意味着private,但有一个例外,即继承类可以访问它(作为private变量)。 - Klaus Byskov Pedersen
@Klaus,谢谢你的解释。我之所以问是因为MSDN上的例子并没有很好地说明这一点,因为代码位于B类的一个静态方法中。 - David Tang

12

9
-1:没有回答“为什么我们要使用它”的问题。 - Timwi
但是先生,根据您的回答,我们可以使用私有(private)而不是声明受保护(protected)。 - Nishant Kumar
4
“私有”限制成员仅可被这个类使用,而不对其他类可见。 - Steve Townsend
@Nishant - 没错,我应该说明一下 protected 和 private 之间的区别(就像 @Steve Townsend 所做的那样)。 protected 隐藏成员变量对于客户端不可见,但仍然对子类可见。 - Andreas Paulsson

7

直接来自MSDN:

protected关键字是成员访问修饰符。受保护的成员可以在其类内部以及由派生类实例访问。

来源

使用protected意味着您可以在一个类中拥有功能,这些功能可供派生类使用,但不可供仅实例化对象的类使用。

此页面比较了不同的访问修饰符,并解释了它们的含义,并给出了默认修饰符的表格(枚举、类、接口和结构)。


6

在另一个答案中提供了定义。这为什么是好的呢?因为当使用protected时,派生类可以访问基类实现,而不必在派生类中复制数据/代码,同时避免了public所暴露的不受限制的外部使用。


3
这意味着该字段仅对类本身和继承的类可见。

3

可以这样理解。一个类提供了三个接口:

  1. 对于自身,具有完全访问内部实现细节的权限(公共、受保护和私有方法和属性)。根据定义,您在类中所做的任何事情都可能影响其他任何事情。
  2. 对于其客户端,仅具有公共方法和属性的访问权限。为了最小化更改的意外后果,您需要将类的公共接口最小化:代码了解您的内部越少,以后就可以更自由地修改它们。
  3. 对于其后代,具有公共和受保护方法和属性的访问权限。无论您对受保护和公共方法做什么,都会影响不仅客户端,还会影响修改类基本功能的后代。面向对象编程是关于减少耦合和增加内聚性的:与继承关系之间没有比这更强的类之间耦合(当然,除了C++的friend之外)!
第三个接口是面向对象中最具挑战性的设计问题:哪些成员(虚拟方法和属性)可以被合理地覆盖,并且为了实现覆盖,需要哪些其他功能(纯粹的受保护方法和属性)?由于这是一个如此大的挑战,因此默认情况下使用 sealed 类实际上是个好主意,尽管对于面向对象的初学者来说似乎是不必要的障碍。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接