阐明我对 C# 封装的理解

Clarifying my Understanding of Encapsulation in C#

这几天我一直在想封装,想知道我的理解是否正确。

是封装,当你创建一个class或结构时,在class或结构内部创建你不想要其他classes或结构的私有变量和方法访问,然后创建 public 方法来读取、写入或使用其他 classes 或结构中的私有变量和方法?

如果是这样,你为什么要这样做?你怎么知道什么时候用这个?与不使用封装相比,这有什么优势?如果可能,是否可以提供一些 "bad" 代码的示例,这些代码将从封装中获益?

感谢您花时间阅读我的问题。

封装用于更明确地定义class的[预期]行为。

假设你有一个 Person class 像这样:

public class Person
{
    public int Age { get; set; }
    public string Name { get; set; }
}

一个 [真实] 人的年龄只会增加,所以你为什么允许任何人重新分配它?

相反,您可以封装年龄,使其必须遵循其预期行为(代价是编写更多代码来处理分配/获取值),如下所示:

public class Person
{
    private int _age = 0;
    public int Age { get => _age;  }
    public string Name { get; set; }

    public void Birthday()
    {
        _age += 1;
    }
}

这样可以保证年龄永不下降

把我的两分钱放进去。

对于封装,基本上有两个原因。

  1. 保护。
  2. 组织。

您必须意识到,您编写的代码不仅供您自己使用,还供其他人阅读和使用(他们无法更改您的代码),尤其是在您创建库或框架时。当其他人使用您的 class/library 时,他们不会想到您的 class 的所有实施细节。他们希望您的代码在直观使用时能够正常工作。

组织:

将相关信息放在正确的位置。例如在 c# List<T> 中有一个 属性 Count,很自然地要跟踪你的列表中有多少项,用户自然会询问我的列表中有多少项。跟踪它应该是 List class 的责任,而且更容易。如果你不提供这个 属性 怎么办?使用必须自己跟踪它。每次想知道列表中有多少项,都得自己写重复的代码和逻辑来统计。当您在 'List' 之外跟踪它时很容易出错,而当它发生在许多 places.The Count 信息自然属于您的 List 时很难进行代码更改class,自然应该留在那里。每次您想知道 Count 时,只需询问您的 List Object.

保护:

为了保护您的对象内部状态在使用过程中始终正确。 来自 about 的相同示例。 'Count' 属性 实际上是 public 读写。 当你实现 Add Remove 时,你会记得增加或减少 Count ,你会记得保护你的 Count 与列表中的多少项目同步并且永远不会低于0。想象一下,如果没有封装,一切都是public。没有什么能阻止用户或你自己在 10 年后做 Count = -100(相信我,其他用户或你自己在 10 年后会这样做),然后你的 List 对象完全变成 none-感觉。并且它会产生许多难以发现的错误,甚至会造成真正的巨大损失,永远不要低估一个程序的破坏力 错误可以做到。