如何在 private 和 protected 访问修饰符之间进行选择以封装 base 和 childs 类 之间的成员?

How to choose between private and protected access modifier to encapsulate members between base and childs classes?

我正在尝试在我的内部函数中使用私有值的项目。过去我只使用 public 个,但我注意到在使用尽可能多的私有参数时混淆效果更好。

我的问题是关于 Parent/Child classes.

在我的主 class 中,我将所有参数定义如下:

public class MyFatherClass
{
    private long id = -1;
    public long ID { get { return this.id; } set { this.id = value; } }    
    ...
}

所以在所有内部函数中我访问我的私有值而不是 public 一个。

然后在我的女儿 class 我只是添加特定于 child class 的参数。

public class MyChildClass : MyFatherClass
{
    private long anotherParameter = -1;
    public long AnotherParameter { get { return this.anotherParameter; } set { this.anotherParameter = value; } }    
    ...
}

只是,我看到在我的 Parent class 中,我可以毫无问题地访问 idID,但是从女儿 classes我只能访问 ID(因为 id 是私有的)。

如果我理解正确的话,我需要将 parent 姑娘中的所有 private 替换为 protected,这样就可以解决问题了吗? 我不明白的是,即使我不这样做,代码也能正常工作。 为什么我没有错误信息,当我在女儿class中设置ID值时,this.id=value这句话被执行了,但是我怎么能从我的[=49访问它呢? =] class 如果是私有的?

我现在在犹豫,我可以在每个child class中添加一个private id,还是可以在我的parent中设置id保护] class?

感谢您的解释。

编辑,只是添加了我混淆后的逆向代码的屏幕截图,以便您了解混淆方式的差异private/public methods/fields

这里是对访问修饰符的作用的简短描述:

  • Public :字段(变量)和属性(变量封装)和方法(函数和过程)是可见的,可通过 class itslef,由它的孩子和任何其他外部 classes.

  • Private:成员(字段、属性和方法)仅对 class 可见和可访问,其子项或任何子项均不可见和可访问外部 class.

  • Protected:成员对 class 及其子项可见和可访问,但对其他 classes 不可见和可访问。

  • Internal :成员对 class 及其子项以及 class 中的任何 class 可见和可访问相同的程序集(.exe 和 .dll),但不是来自另一个程序集的 class。

所以你应该在 parent class 中将 id 设置为受保护,以便在孩子中使用它。

但这是规则:

  • 如果孩子 classes 可以修改 id 你应该设置为受保护的字段,并提供 public 属性 (get) 如果可用于外部项目.

  • 如果孩子 class 不允许修改它,您应该将其设置为私有并提供:

    • 预期的 属性 如果外部项目无法访问它,则只有 getter。

    • A public 属性 只有 getter 如果外部项目可以访问它。

不要重复同名成员,否则它会隐藏 parent 并可能导致多态性问题,否则你知道你在做什么。

您可以阅读这些教程以更深入地了解访问修饰符关键字:

C# Access Modifiers

Access Modifiers (C# Reference)

这里有一些读物:

C# Tutorial Level 0
C# Tutorial Level 1
C# Tutorial Level 2
C# Tutorial Level 3

C# Snippets @ Techi.io

Beginning Visual C# 2008 Programming

Why don't I have an error message, when I set ID value in daughter class, the sentence this.id=value is executed, but how can can I access to it from my child class if it is private?

当您在 class 上调用 public 方法时,该方法可以访问 class 的私有成员:

public class Foo
{
    public void Bar()
    {
        Baz();
    }

    private void Baz()
    {
        // private method called by public method
    }
}   

var foo = new Foo();
foo.Bar();

这编译得很好。您的 setter 是相同的:它是 public,因此可以从任何地方调用,即使它访问私有成员也是如此。

至于使您的字段 (private long id = -1;) 受到保护:是的,这意味着您可以在派生的 classes 中访问它。但你愿不愿意就是另一个问题了。

您声明 public 属性 是有原因的。也许您想在其 setter 或 getter 中进行一些验证。如果不是,如果您只是使用 属性 访问私有字段,您可以放弃整个私有字段并使用自动实现的 属性:

public long ID { get; set; } = -1;

然后你可以在任何地方访问 属性,从它本身,从派生的 classes 和使用这个 class.

的代码

另请参阅:

  • What is the difference between a field and a property?
  • What are Automatic Properties in C# and what is their purpose?

继承自 MyFatherClassMyChildClass class 无法访问 id 字段 因为 它是私有的。要使其可访问,您需要将字段的访问修饰符更改为:

protected :

////////////////////////////////////
// Dll1.dll
////////////////////////////////////

namespace Dll1
{
    public class Base
    {
        //The field we are attempting to access
        protected int a;
    }

    public sealed class Main : Base
    {
        public void DoSomething()
        {
            //Can be done sins Main inherits from Base
            base.a = 100;
        }
    }

    public class Invader
    {
        public int GetA()
        {
            var main = new Main();

            main.DoSomething();

            // can not be done sins the field is only accessible by those that inherit from Base
            return main.a;
        } 
    }
}

////////////////////////////////////
// Dll2.dll
////////////////////////////////////

namespace Dll2
{
    public class ADll2Class : Dll1.Base
    {
        public int GetA()
        {
            //Can be done because ADll2Class inherits from Dll1's Base class
            return base.a;
        }
    }

}

private protected :

与受保护相同,但在上面的示例中,Dll2 的 class、ADll2Class 将无法访问 a 字段,因为它会受到私有保护,在其他情况下只有来自与 Base 相同的 dll 的 classes 继承自 Base 才能访问 a.

或者您可以将其设置为

internal :

如果上面示例中的 a 字段是内部字段,那么,与 private protected 相同,Dll2 的 class 将无法访问它,但是 Invader class 在 Dll1 中将能够访问它,因为它是与 Base.

相同的 dll 的一部分

请注意,您提到混淆的罪过,请尽您所能,id 字段在 reflection 的帮助下仍然可以被其他人以混淆状态访问,尤其是您的罪过提供一个 public 属性 ID,不妨将项目中的所有内容设置为 internal.