【问题标题】:When should we use public and when private?我们什么时候应该使用公共的,什么时候应该使用私有的?
【发布时间】:2023-04-02 23:55:01
【问题描述】:

当我们在我们的团队解决方案中实现目前未被其他类使用的方法时,访问修饰符应该是公共的还是私有的? 我相信“一个公共成员说这个成员代表了这个对象提供的关键的、记录在案的功能。”。我们只将“实现细节”方法设为私有,所有将来可能有用的方法都应该公开,即使现在其他类中没有我们方法的消费者。但是我的对手说这样的方法应该是私有的。你觉得怎么样?

添加: 让我们更具体一点。例如有一个类SqlHelper。 其中有用于操作 SQL Server 的有用功能。 特别是使用到 SQL 服务器的连接。但不仅在那个班级。

例如,我需要实现将处理 SqlExeptions 的公共静态 HandleSqlExeption 方法(现在仅适用于 SqlHelper 类)。但我希望在所有在异常处理中使用 SQL 连接进行操作的类中都将使用此方法(而不是简单,例如: 捕捉(异常){ MsgBox {“SqlError”}; 正如某处现在发生的那样。所以我认为公共访问修饰符会告诉其他同事他们可以使用这种方法。而 private 将隐藏该方法。如果有人要求使用这种方法,我将需要更改代码并重新构建程序集。为什么?只有负面的。

【问题讨论】:

  • 阅读这个 MSDN 链接,它解释得很清楚Access Modifiers
  • 我的经验法则:一切都应该是private,直到你真正需要它是public(或internalprotected等)
  • @leppie:我的经验法则是 100% 的相反。作为类提供的连贯接口的一部分以及它提供的逻辑功能的所有内容都应该是公共的。 (有趣的是,我们的两条规则可能会在 98% 的情况下达成一致。)

标签: c# .net coding-style


【解决方案1】:

一般来说,您应该使用尽可能少的许可访问修饰符进行编码。

  • 如果方法不在类外使用,则设为private
  • 如果方法需要继承类型使用,则设为protected
  • 如果该方法只在程序集中使用,请将其设为internal
  • 仅当方法要在程序集之外使用时,它才应该是public

这对information hiding 有帮助,让您可以随意更改实现。

我听说这被描述为保护你的隐私。


在 API 设计方面,您应该有一个完整的 API,将所有逻辑功能公开为 public - 这就是为什么您应该在 .NET 中使用接口进行 API 设计的原因,因为所有接口成员都必须是 public。在实现类时,对不属于接口的任何成员使用上述经验法则 - 除非它们构成接口的逻辑部分,就其使用者而言。


因此,如果您今天使用了Read 方法,那么您应该有一个具有相同 可访问性的补充Write 方法。这是一个很好的设计(对称且符合预期),但是如果公共方法使用它们,如何您阅读或写入的方式应该隐藏在私有方法后面。

【讨论】:

  • 但是如果明天其他人需要这种方法怎么办?我认为他会更容易发现他可以使用安全的公共方法。此外,他为自己的需要编写相同功能方法的机会也将减少。
  • 是的,但是如果你有“下一个”和“上一个”方法在目的和实现上是对称的,你不会仅仅因为你碰巧就决定公开“上一个”而不是“下一个”拥有名为“previous”的代码,并且已经编写了任何名为“next”的代码。您想呈现一个连贯、完整的界面。
  • @BransDs - YAGNI。如果明天需要,您明天更改访问修饰符。
  • @DavidSchwartz - 当然。这就是为什么我说“一般”。这是一个很好的经验法则。
  • @Oded:对,这就是我的立场——提供一个完整且连贯的界面,提供一些逻辑功能。设计一个类来提供客户需要的功能,而不是客户需要的功能。然后客户端可以通过调用该类提供的函数来获得该功能。 “如果明天需要,明天更改访问修饰符”太疯狂了。如果它是类的逻辑功能的一部分,请立即将其公开。如果没有,明天不要公开。
【解决方案2】:

根据名称描述的方法的性质使用公共和私有。

public当方法可以暴露给其他对象和

private 当方法不应该被其他对象访问时。

如果您的对象需要更安全,请使用private 访问说明符。您还应该了解protected 访问说明符,它的不同之处在于,这些方法只能由继承它们的对象访问。

【讨论】:

    【解决方案3】:

    如果一个类有一些东西要暴露给外界,那么就让它公开,否则就是私有的。这取决于类的功能和目的,而不是当前或未来的要求。

    【讨论】:

      【解决方案4】:

      这是一个判断电话。一般来说,如果它在逻辑上是类为获取它提供的功能而呈现的接口的一部分,那么即使它没有当前用户,它也应该是公共的。这将减少每次您想要将其用于您已经在使用它的基本相同的事情时都需要修改该类的机会。

      但是,这是有代价的。您公开的每个功能都是您承诺提供的功能。如果将来您决定将其从公共界面中删除,您可能会破坏调用者。

      例如,考虑一个地图类。假设您目前没有任何调用者需要知道地图中的项目数,并且您当前的实现有一个 size 变量,您可以轻松返回。您可以添加一个返回地图大小的getSize 函数。它在逻辑上是地图类公开的功能的一部分。因此,即使当前调用者不需要知道大小,人们也可以争辩说它应该是公开的。

      但是,未来的实现完全有可能希望摆脱size 变量。也许增加和减少大小的开销很大,并且实现更改为不需要知道大小。如果你暴露了getSize 函数并且它被调用了,你要么必须继续跟踪大小,即使你不需要它,要么使函数非常昂贵,不得不实际计算大小。

      假设很多代码需要知道表是否为空,您为此提供了isEmpty 函数。经验表明,如果您还提供getCount 函数,人们会使用getCount() == 0 而不是isEmpty。这在今天可能没有任何区别,但它可能会限制您未来的实施选择,以使 getCountisEmpty 一样便宜。

      如果可能,我强烈建议您将其公开,前提是您可以轻松想象该类的正常用户将受益于访问该功能,并且它构成了该类提供的功能的逻辑部分。否则,无论如何,您以后都可以轻松添加它。所以不要过分强调它。这主要是一个风格问题,混合着试图预测未来。

      【讨论】:

      • 我添加了示例。怎么样。你怎么让这个SqlExeption处理方法应该是私有的还是公有的?
      • @BransDs:这个类使用 SQL 并且可以抛出 SqlExceptions 的事实是内部实现细节吗?或者它具体是一个 SQL 类?如果碰巧使用 SQL 存储事物这一事实是一个实现细节,那么这绝对应该是私有的。如果它是一个 SQL 类,并且使用它的每个人都知道它可以抛出这样的异常(它们目前恰好不在乎),那么它可能应该是公共的。 (虽然这里有点代码味道。为什么是处理程序?为什么不将异常传递给调用者?)
      【解决方案5】:

      面向对象开发的基本原则;一个类的实例应该只公开它的客户需要访问的内容。请参阅link 并搜索“封装”。

      【讨论】:

      • 请注意,这包括未来的客户,而不仅仅是当前的客户。这不是“当前客户只是碰巧做了什么”,而是该类旨在提供什么功能,以便其接口是一个完整、连贯的逻辑单元。
      猜你喜欢
      • 2021-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-22
      • 1970-01-01
      • 2023-04-02
      • 2011-04-15
      • 2017-04-10
      相关资源
      最近更新 更多