75

我需要公开一个类实例的“被映射? ”状态。结果由基本检查确定。它不仅仅是暴露一个字段的值。我不确定是否应该使用只读属性或方法。

只读属性:

public bool IsMapped
{
    get
    {
        return MappedField != null;
    }
}

方法:

public bool IsMapped()
{
    return MappedField != null;
}

我已经阅读了 MSDN在属性和方法之间的选择,但我仍然不确定。

4

12 回答 12

90

C# 标准说

§ 8.7.4

属性是提供对对象或类的特征的访问的成员。属性的示例包括字符串的长度、字体的大小、窗口的标题、客户的姓名等。属性是字段的自然扩展。两者都是具有关联类型的命名成员,访问字段和属性的语法相同。但是,与字段不同,属性不表示存储位置。相反,属性具有指定在读取或写入其值时要执行的语句的访问器。

而 as 方法被定义为

§ 8.7.3

方法是实现可由对象或类执行的计算或动作的成员方法有一个(可能是空的)形式参数列表、一个返回值(除非方法的返回类型是 void ),并且是静态或非静态的。

属性方法用于实现封装。属性封装数据,方法封装逻辑。这就是为什么在公开数据时应该首选只读属性的原因。在您的情况下,没有修改对象内部状态的逻辑。您希望提供对对象特性的访问

您的对象的实例是否是您的对象IsMapped的特征。它包含一个检查,但这就是你有属性可以访问它的原因。可以使用逻辑定义属性,但它们不应暴露逻辑。就像第一个引用中提到的例子一样:想象一下这个String.Length属性。根据实现的不同,该属性可能会遍历字符串并计算字符数。它也确实执行了一项操作,但“从外部”它只是给出了一个关于对象内部状态/特征的声明。

于 2013-05-30T07:22:32.660 回答
22

我会使用该属性,因为没有真正的“做”(动作),没有副作用,而且不太复杂。

于 2013-05-30T06:53:37.030 回答
13

我个人认为 amethod应该做某事或执行某些动作。您没有在内部执行任何操作,IsMapped因此它应该是property

于 2013-05-30T06:53:46.760 回答
7

我会去买房。主要是因为引用的 MSDN 文章的第一句话:

一般来说,方法代表动作,属性代表数据。

于 2013-05-30T06:54:34.223 回答
5

在这种情况下,我似乎很清楚它应该是一个属性。这是一个简单的检查,没有逻辑,没有副作用,没有性能影响。没有比那个检查简单得多的了。

编辑:

请注意,如果有上述任何一种,并且您将其放入方法中,则该方法应包括一个强动词,而不是像 is 或 has 之类的助动词。方法做某事。您可以将其命名为 VerifyMapping 或DetermineMappingExistance 或其他名称,只要它以动词开头即可。

于 2013-05-30T06:54:13.633 回答
5

我认为您链接中的这一行就是答案

方法代表动作,属性代表数据。

这里没有动作,只是一条数据。所以它是一个属性。

于 2013-05-30T06:54:31.060 回答
4

在您可以访问这两种结构的情况/语言中,一般划分如下:

  • 如果请求是针对对象拥有的东西,请使用属性(或字段)。
  • 如果请求是针对对象所做的某事的结果,请使用方法。

更具体地说,属性将用于以读取和/或写入方式访问由暴露该属性的对象拥有的数据成员(用于消费目的)。属性优于字段,因为数据不必一直以持久形式存在(它们允许您“懒惰”地计算或检索此数据值),并且它们优于用于此目的的方法,因为您仍然可以在代码中使用它们,就好像它们是公共字段一样。

但是,属性不应导致副作用(可能的,可以理解的例外是设置一个旨在保持返回值的变量,避免需要多次重新计算昂贵的值);在所有其他条件相同的情况下,它们应该返回确定性结果(因此 NextRandomNumber 对于属性来说是一个糟糕的概念选择),并且计算不应导致任何会影响其他计算的状态数据的更改(例如,获取 PropertyA 和按该顺序的 PropertyB 不应返回与获取 PropertyB 和 PropertyA 不同的结果)。

方法OTOH在概念上被理解为执行一些操作并返回结果;简而言之,它做了一些事情,可能超出了计算返回值的范围。因此,当返回值的操作具有额外的副作用时,将使用方法。返回值可能仍然是某些计算的结果,但该方法可能已对其进行了非确定性计算(GetNextRandomNumber()),或者返回的数据是对象的唯一实例的形式,再次调用该方法会产生一个不同的实例,即使它可能具有相同的数据 (GetCurrentStatus()),或者该方法可能会更改状态数据,从而连续两次执行完全相同的操作会产生不同的结果 (EncryptDataBlock();

于 2013-05-30T20:35:53.883 回答
3

如果在任何时候您都需要添加参数以获取值,那么您需要一个方法。否则你需要一个属性

于 2013-05-30T06:54:31.073 回答
2

恕我直言,第一个只读属性是正确的,因为 IsMapped 作为对象的属性,并且您没有执行操作(仅评估),但最终与现有代码库的一致性可能超过语义......除非这是一个单一的分配

于 2013-05-30T06:58:09.723 回答
2

我同意这里的人的说法,因为它正在获取数据并且没有副作用,所以它应该是一个属性。

为了扩展这一点,如果副作用对“从外面看”的人有意义,我也会接受一些带有 setter(但不是 getter)的副作用。

一种思考方式是方法是动词,属性是形容词(同时,对象本身是名词,静态对象是抽象名词)。

动词/形容词准则的唯一例外是,在获取(或设置)相关信息时使用方法而不是属性可能会非常昂贵:从逻辑上讲,这样的功能应该仍然是属性,但是人们习惯于将属性视为对性能的影响较小,虽然没有真正的理由为什么总是如此,但GetIsMapped()如果事实确实如此,那么强调相对较重的性能可能会很有用。

在运行代码的层面上,调用属性和调用等效方法来获取或设置完全没有区别;这一切都是为了让编写使用它的代码的人的生活更轻松。

于 2013-05-30T11:13:16.483 回答
1

我希望属性,因为它只返回字段的详细信息。另一方面,我希望

MappedFields[] mf;
public bool IsMapped()
{
     mf.All(x => x != null);
}
于 2013-05-30T07:34:17.107 回答
0

你应该使用这个属性,因为 c# 有这个原因的属性

于 2013-05-30T12:09:22.340 回答