C#自动属性

53

我对 C# 中的自动属性有些困惑,例如:

public string Forename{ get; set; }

我理解你通过不声明私有变量来节省代码,但是如果你没有使用任何 get 或 set 逻辑,那么属性的意义是什么呢?为什么不直接使用

public string Forename; 

我不确定这两个语句的区别在哪里,我一直认为如果你想要额外的get/set逻辑,你会使用属性(properties)?


1
可能是在C# .NET 3.5+中属性和字段的区别的重复问题。 - nawfal
11个回答

118

属性可以在不违反契约的情况下放置代码,而字段则无法放置代码,除非将其更改为属性(并破坏接口)。属性可以是只读或只写的,而字段不能。属性可以进行数据绑定,而字段则不能。


你必须放置自己的后备字段。自动属性现在让你不用担心这个问题,但仍要为未来做好计划 - 有关详细信息请参阅我的答案。 - Reed Copsey
4
自动属性很简单,也很笨。要添加逻辑,你需要将其转换为普通属性。无论是获取还是设置都可以是自动属性,或者两者都不是。 - Nader Shirazie
+1 我听过很多解释,这个是迄今为止最清晰的一个。 - Robert Harvey
@Gav:差不多。它们还比字段(因为它们是属性)允许更多的数据绑定选项,并且比字段提供更精细的访问控制。 - Reed Copsey
1
这也成为了一个控制问题。如果任何代码都可以设置字段,那么类模块就失去了控制权,无法知道字段可能具有的值。这可能会使错误更难以发现,甚至可能会创建难以重现和查找的错误。 - Jeff Siver
显示剩余2条评论

15
你可以编写:

public string Forename{ get; private set; }

要获取只读属性... 这仍然不如真正的属性灵活,但对于有些情况来说是一个妥协。


13

我不确定这两个语句之间的区别,我一直以为如果想要额外的get/set逻辑就使用属性呢?

在第一种情况下,编译器将自动为您添加一个字段,并包装属性。这基本上相当于执行以下操作:

private string forename;
public string Forename
{
    get
    { 
        return this.forename;
    }
    set
    {
        this.forename = value;
    }
}

使用属性(properties)比使用字段(fields)有许多优点。即使您不需要一些特定的原因,比如数据绑定,这也可以帮助未来证明您的API(应用程序编程接口)。

主要问题在于,如果您创建了一个字段,但在应用程序的v2中需要属性时,则会破坏API。通过最初使用自动属性,您有可能随时更改API,而无需担心源代码或二进制兼容性问题。


6

这意味着您希望稍后添加逻辑。

如果您从一开始就将其作为属性添加,您将不必重建相关代码。如果您将其从变量更改为属性,则必须重新构建相关代码。


2
这是不正确的。并不是说您希望稍后添加逻辑。没有任何地方暗示这样的意图。它只是为了使编写正确代码(属性 vs. 字段)更容易而采用的简写方式。 - Charles Boyung

4

2

公共数据成员有害(因为对象无法控制其自身状态的修改 - 它变成了全局变量)。破坏了封装 - 面向对象编程的原则。

自动属性存在是为了提供封装,并避免为简单属性编写样板代码的繁琐。

public string ID { get; set;}

您可以将自动属性更改为非自动属性,以便在未来进行修改(例如,您在setter中进行了某些验证),而不会破坏现有的客户端。
string m_ID;
public string ID
{
   get { return m_ID; }
   set 
   { 
     //validate value conforms to a certain pattern via a regex match
     m_ID = value;
   }
}

你无法对公共数据属性执行相同的操作。将数据属性更改为属性将强制现有客户端重新编译,然后才能再次进行交互。

1
这在一定程度上是正确的,但公共属性并不比公共数据更好地封装了数据: OOP 的信条之一是“告诉而不是问”,而使用属性(来获取对象的内部状态)仍然是在问而不是告诉。 - ChrisW
2
嗯...我不太同意,我认为公共属性比全局变量好得多。告诉别人而不是问 - 我认为这是良好面向对象设计的一条启发式原则;当然也有例外,例如如果一个类负责轮询n个设备并公开总体状态,则其工作是计算和传达最新状态 - 你必须“询问”,不同的客户端可能会根据状态采取不同的操作。数据访问层(DAL)也需要询问方法。 - Gishu

2

当添加自动属性时,编译器将在应用程序中添加get set逻辑,这意味着如果您稍后添加到此逻辑,并且外部库引用您的属性,仍将起作用。

如果您从公共变量迁移到属性,则对于引用您的其他库来说,这将是一种破坏性的变化 - 因此,为什么不从自动属性开始呢? :)


非常好的回答。在你提到引用之前,我认为没有任何区别。 - Mark Beckwith

1
一方面,您可以将属性设置为虚拟的,并在继承类中实现逻辑。 您还可以在同一类中之后实现逻辑,并且不会对依赖于该类的任何代码产生副作用。

1

并非所有属性都需要get/set逻辑。如果需要,可以使用私有变量。 例如,在MV-something模式中,您的模型不会有太多逻辑。但是您可以根据需要混合和匹配。

如果您要使用像您建议的字段来替换属性,则无法定义接口以正确描述您的类,因为接口不能包含数据字段。


1
一个属性就像是一个合同,你可以更改属性的实现方式而不影响使用你的类和属性的客户端。今天你可能没有任何逻辑,但是随着业务需求的变化,如果你想引入任何代码,属性是最安全的选择。以下两个链接是优秀的C#视频教程。第一个视频解释了为什么需要属性而不仅仅使用字段,第二个视频解释了不同类型的属性。我发现它们非常有用。

C#中属性的必要性

C#中的属性,只读,只写,读/写,自动实现


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