为什么C#自动实现属性是公共的?

7
在我看到的所有示例中,C#自动实现的属性都是公共的,即使在MSDN文档示例中也是如此。从C++背景出发,我一直被教导说,除非有充分理由,否则将成员数据设置为私有是一个好主意。
为什么从未使用以下代码(至少我从未见过):
private Name { get; set; }

我查看了MSDN文档并阅读了几篇介绍自动属性的教程,但没有任何关于它们的优缺点以及何时应该避免使用它们的建议。自动属性是否会影响程序安全性?是否有需要避免使用它们的情况?在哪些情况下它们是理想的选择?谢谢。

2
你把 C# 属性和 C# 字段混淆了。 - BoltClock
Java 中的 protected 关键字更糟糕。 - Moog
3
我理解问题是Terribad问为什么人们使用public int Foo { get; set },也就是说,为什么人们创建公共自动实现属性?虽然可以创建私有属性,但在我的经验中它们非常罕见。因此,我认为对这个问题打负分有点过分了:我认为OP有一个合理的问题。 - Daniel Pryden
@Daniel Pryden:是的,这正是我想问的。 :) 为什么我读到的每个自动实现属性示例都是公用的,从未是私有的? - InvalidBrainException
1
@John Saunders:显然他们可以。我的问题是:为什么它们似乎总是在示例中公开? - InvalidBrainException
显示剩余3条评论
6个回答

8

你是正确的,自动实现的属性只是暴露一个后备字段,与公共字段相比并没有太大的优势。

正如Alan Kay所说

但是,大多数使用setter的人只是用它们来模拟对内部变量的直接赋值,而这违反了真正面向对象编程的精神和意图

然而,自动实现的属性与公共字段相比有一个优点,那就是它对于稍后修改实现来说是非破坏性的。如果你有一个公共字段,并且类外的代码操作该公共字段,你不能在以后的版本中将其更改为私有字段,否则任何触及该字段的其他代码都必须重新编译。相比之下,一旦你拥有一个公共属性,你可以在未来版本中修改该属性的实现,客户类可以继续使用它而不需要进行任何更改。

因此,对于那些现在具有简单 getter 和 setter 实现,并且将来可能具有更复杂实现的属性,使用自动实现属性是很有用的。


5
你是否曾经想过为什么一直被教导将成员设为私有变量呢?这是因为(除了其他原因之外)字段是实现细节,它是“存储数据在内存中”的细节。对于希望检索或设置数据的任何对象来说,这是一个不重要的细节。另一个类不需要关心它是否可以访问某个内存位置-他只想要一个接口,通过该接口他可以传递或检索值-这就是获取器和设置器或属性。
我们将属性与“基于内存存储”的细节分离后,我们得到了许多优势。主要是-我们可以覆盖获取和设置的行为,而不会影响使用该属性的任何代码。我们还可以使用属性作为检索不同实现的数据的抽象。这对于测试/模拟行为和提供替代存储非常有用。如果其他类依赖于“内存存储”的实现细节,则无法更改类的行为而不破坏所有这些类。
在自动属性出现之前,我们通常会存储字段并创建一个getter和setter来封装它,以实现上述原因。自动属性为我们自动化了这个过程。我们可以编写通常在代码的各个地方都使用字段的代码,但是我们保持“我现在会将其作为字段处理,但如果标准改变,这可能会受到更改”的想法。
由于类知道自己的实现,创建私有自动属性通常是一种毫无意义的尝试,您并没有隐藏已知的细节。如果需要向子类公开,则受保护的自动属性可能很有用。
至于应避免使用它们的情况:当您需要只读数据时(即对象构造后不会更改的数据)。自动属性缺乏语法以允许您创建由只读数据支持的自动化属性。

1
谢谢详细的解释。关于你最后一段话,我认为这是在最新的C#版本中创建不可变自动属性的一种方式: public Name { get; private set; } - InvalidBrainException
2
这只是将属性对外部对象设置为“只读”,而不是对类本身设置。它的功能与字段上的 readonly 关键字不同。 - Mark H

3

自动实现属性有一个私有的后备成员。编译器会为您添加它们。这只是一种快捷方式,相当于:

private int _aMember;
public int AMember {
           get {return _aMember;} 
           set {_aMember = value;} 
}

如果你使用getter/setter方法,除了需要封装的需求外,并没有真正的逻辑。


2
自动属性只是一种常见模式的快捷方式。在C++中,每当您有一个私有成员和相应的get和set函数时,您可以使用C#中的自动属性来完成相同的事情。它们不会引入任何不同的最佳实践或安全问题。

2

使用自动属性的公共getter和setter是使用简单get和set实现的私有备份字段的快捷方式。

您应该将它们视为类似于C++中具有公共get和set方法的私有字段。这是C#中属性的角色。


1

属性不是“成员”数据。它们有点像您自己的。

const T& field() const;
T& field();

类型的事物,或者获取和设置方法,即它们是访问器。

如果您不需要公开成员,请不要在属性中表达它们。 对于自动生成的成员,您可以简单地(根据我的了解,从C# 2.0开始)编写

int SomeProperty { get; private set; }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接