What is the use case for the (C# 7.2) "private protected" modifier?

C# 7.2 introduces the private protected modifier.

I've always protected access to fields with properties, allowing access via the Get/Set methods as I typically don't want the internal state of my object modified by anything other than my own class.

I'm trying to understand why the C# language team have added this feature. After an extensive search on google, and reading and watching the 'what's new' media (I've watched the press release, details and video by Mads Torgerson), I am still none the wiser.

To me, this appears to allow a developer to break the Liskov Substitution principle, but this may be because I do not understand why this feature now exists.

I understand how it can be used, just not why - please can someone provide a real-world usage example rather than the contrived one in the MSDN documents?

9549 次浏览

在 C # 7.2之前,我们有 protected internal修饰符。这实际上意味着受保护的或内部的,即-member A可以被子类访问,也可以被当前程序集中的任何类访问,即使那个类不是类 A的子类(所以“ protected”暗示的限制被放宽了)。

private protected实际上意味着受保护的和内部的。也就是说-member 只能被同一程序集中的子类访问,而不能被程序集外的子类访问(因此“ protected”隐含的限制被缩小了——变得更加严格)。如果在程序集中生成类的层次结构,并且不希望其他程序集的任何子类访问该层次结构的某些部分,则此选项非常有用。

我们可以举一个例子,Jon Skeet提供了 在评论中。假设你有类

public class MyClass {


}

并且您希望只能在当前程序集中从它继承,但不希望允许直接实例化此类,除非是从此类层次结构中实例化。

只能在当前程序集内继承,可以通过内部构造函数实现

public class MyClass {
internal MyClass() {
}
}

可以使用受保护的构造函数来实现除当前类层次结构外的直接实例化:

public class MyClass {
protected MyClass() {
}
}

要同时得到这两个函数,你需要 private protected构造函数:

public class MyClass {
private protected MyClass() {
}
}

假设您有一个名为 SomeHelper的内部类,希望将其用作公共抽象基类实现的一部分:

public abstract class Test
{
// Won't compile because SomeHelper is internal.
protected SomeHelper CreateHelper()
{
return new SomeHelper();
}


public int Func(int x)
{
var helper = CreateHelper();
return helper.DoSomething(x);
}
}


internal class SomeHelper
{
public virtual int DoSomething(int x)
{
return -x;
}
}

这将无法编译,因为不能让受保护的方法返回内部类型。你唯一的办法就是不要那样使用 SomeHelper,或者公开 SomeHelper

(您可以使 SomeHelper成为受 Test保护的内部类,但是如果 SomeHelper被其他不从基类派生的类使用,那么这种方法就不起作用了。)

随着 private protected特性的引入,你可以这样声明 CreateHelper():

private protected SomeHelper CreateHelper()
{
return new SomeHelper();
}

现在它将编译,而且您不必公开您的内部结构。

对于 两个字访问修饰符,我有这个概念——第一个访问器与另一个程序集相关,第二个访问器与定义它的程序集相关。

内部保护

  • Protected 在另一个程序集中: 只能在子类中访问。

  • 内部 在当前程序集中: 可由当前程序集中的每个人访问。

私人保护

  • 另一个程序集中的 private 无法访问。
  • Protected 在当前程序集中: 只能在子类中访问。

内部保护 意味着“受保护或内部”-任何类型/成员定义了这个访问修饰符可以在以下场景中访问-(A)在同一个程序集,(B)类是定义在另一个程序集,从容器类派生

私人保护 意味着“受保护和内部”-使用这个访问修饰符定义的任何类型/成员都可以在以下场景中访问-从容器类继承并属于同一程序集的类