【问题标题】:Should we use struct for data and class for behavior?我们应该将结构用于数据,将类用于行为吗?
【发布时间】:2026-02-15 09:30:02
【问题描述】:

Active Record vs ObjectsBob Martin 的文章中指出:

  • 对象隐藏数据并暴露行为
  • 数据结构暴露数据并且没有行为

然后他继续说

在 C++ 和 C# 等语言中,struct 关键字用于描述 具有公共字段的数据结构。

在我看来,他似乎将数据结构用作 struct 的同义词,并说我们应该将 struct 关键字用于数据,将 class 关键字用于实现具有行为的对象。这听起来很奇怪,因为mutable structs are evil 和大多数系统中的数据都需要更改(这意味着大多数数据都是邪恶的)。

有人能指出我推理中的缺陷吗?

【问题讨论】:

  • 我认为“你的推理没有缺陷”;面向对象的设计决策和约定不是保证良好设计的“事实”。这个主题似乎也有点基于意见。所有的设计理念都以一件事换另一件事。

标签: c#


【解决方案1】:

Bob 对活动记录提出了一个很好的观点,但他决定混入 struct 关键字(与概念相反)有点令人困惑..

首先,重要的是要了解 struct 在 C# 和 C++ 中的含义完全不同。

这里是对区别​​的粗略解释:

在 C# 中,关键字 struct 用于定义自定义值类型。 关于这种类型的唯一说明是它总是按值传递给方法(与通过引用传递的引用类型相反。换句话说,当您将值类型传递给方法时,实际上传递了它的副本,并且方法内部对副本的任何更改在其外部均不可见。

在 C++ 中,类和结构几乎相同。结构本质上是一个类,默认情况下所有成员都是公共的。

因此,当您谈论可变结构的邪恶属性时,请记住,这仅涵盖 C#,与 Bob 所说的无关。主要问题是使用它们时违反语义和非常奇怪的错误,但这是另一个问题的讨论。

【讨论】:

  • C#中的所有参数默认是传值的,如果配合ref关键字使用,所有的参数都可以引用传。这与它们是值类型还是引用类型无关。 Type 的类型是值还是引用类型会影响传递的值本身是值还是对别处值的引用。
【解决方案2】:

我不认为这就是 Bob Martin 想要表达的意思。我明白他在说:

  1. 如果您需要行为和数据,请使用类,而实际数据可能(或可能不)感兴趣。
  2. 如果您不想对数据执行任何操作,但仍想对数据的各个值(都是公开的)进行分组,请使用结构

示例 1) 车辆的经典 OO 示例 - 它具有特征(数据)和操作(如驾驶、停止、换档等)

示例 2) 一个示例是地址。它是不可变的,没有立即执行的操作。或者在 2D/3D 空间中取一个点 - 它具有三个坐标,仅此而已。

【讨论】:

  • 绝对可以对地址或点进行操作。还有很多结构有很多操作。
  • 我并不是说这是不可能的。我只是说这是我从 Bob Martin 引用的文字中所理解的。我个人很少创建结构,但在大多数情况下使用类。
  • 在决定在 C# 中使用结构还是类时,不考虑是否计划对类型进行操作。如果您不使用结构,并且不熟悉差异或应考虑哪些因素,那么您不应该回答有关该主题的问题。
  • 我不太确定谁有权让你如此自大,但如果你知道得这么清楚,请随意回答这个问题,而不是那样发表评论。我不知道为什么您认为我不知道类和结构之间的区别,我也不知道您为什么认为 I 区分“具有操作的事物和没有操作的事物” t",但我喜欢重复我之前说过的话:OP 引用了另一位作者的文字。我只是说我认为他误解了作者的意思。
【解决方案3】:

我认为他没有提到数据结构是否可变。您始终可以通过只允许通过构造函数实例化成员来使您的结构不可变。

public struct Foo
{
    private int _bar;

    public Foo(int bar)
    {
       _bar = bar;
    }

    public int Bar { get { return _bar; } }
}

我认为使用结构作为数据分组的一种方式有其用途,特别是对于需要值类型语义的小型短期对象。

【讨论】:

    最近更新 更多