I. *_*edy 333 c# field properties class automatic-properties
我们经常被告知我们应该通过为类字段制作getter和setter方法(C#中的属性)来保护封装,而不是将字段暴露给外部世界.
但是很多时候,一个字段只是用来保存一个值,并且不需要任何计算来获取或设置.对于这些,我们都会这样做:
public class Book
{
private string _title;
public string Title
{
get{ return _title; }
set{ _title = value; }
}
}
Run Code Online (Sandbox Code Playgroud)
好吧,我有一个坦白,我不忍心写所有这些(真的,它不必写它,它不得不看它),所以我去流氓和使用公共领域.
然后是C#3.0,我看到他们添加了自动属性:
public class Book
{
public string Title {get; set;}
}
Run Code Online (Sandbox Code Playgroud)
这更整洁,我很感激它,但是真的,除了创建一个公共领域之外还有什么不同?
public class Book
{
public string Title;
}
Run Code Online (Sandbox Code Playgroud)
Mic*_*tum 168
在我前段时间的一个相关问题中,有一个链接指向杰夫博客上的帖子,解释了一些差异.
将变量更改为属性是一个重大变化.例如:
TryGetTitle(out book.Title); // requires a variable
Run Code Online (Sandbox Code Playgroud)Jar*_*Par 80
忽略API问题,我发现使用属性最有价值的是调试.
CLR调试器不支持数据断点(大多数本机调试器都支持).因此,无法在类的特定字段的读取或写入上设置断点.这在某些调试方案中非常有限.
由于属性是作为非常精简的方法实现的,因此可以在读取和写入其值时设置断点.这使他们在田野上占了一席之地.
Rex*_*x M 68
从字段更改为属性会破坏合同(例如,需要重新编译所有引用代码).因此,当您与其他类(任何公共(通常受保护的)成员)建立交互点时,您希望计划未来的增长.通过始终使用属性来这样做.
今天没有什么可以使它成为一个自动财产,并且在线下3个月意识到你想让它延迟加载,并在getter中进行空检查.如果你使用了一个字段,那么这是一个最好的重新编译更改,最坏的情况是不可能的,这取决于谁和什么依赖于你的程序集.
Mar*_*ner 62
仅仅因为没有人提到它:你不能在接口上定义字段.因此,如果必须实现定义属性的特定接口,则自动属性有时是一个非常好的功能.
像这些微不足道的属性让我感到悲伤。它们是最糟糕的货物崇拜,对 C# 公共领域的仇恨需要停止。反对公共字段的最大论据是面向未来:如果您后来决定需要向 getter 和 setter 添加额外的逻辑,那么您将必须在使用该字段的任何其他代码中进行大量重构。在 C++ 和 Java 等其他语言中当然也是如此,其中调用 getter 和 setter 方法的语义与设置和获取字段的语义非常不同。然而,在 C# 中,访问属性的语义与访问字段的语义完全相同,因此 99% 的代码应该完全不受此影响。
我见过的一个将字段更改为属性的示例实际上是源级别的重大更改,如下所示:
TryGetTitle(out book.Title); // requires a variable
Run Code Online (Sandbox Code Playgroud)
对此我不得不问,为什么 TF 你要传递其他类的字段作为参考?依赖于此,不成为属性似乎是真正的编码失败。假设您可以直接写入您一无所知的另一个类中的数据,这是不好的做法。创建您自己的局部变量并book.Title从中设置。任何执行此类操作的代码都应该被破坏。
我见过的其他反对它的论点:
总而言之,是的,琐碎的属性有一些合法的用途,但是除非您正在制作一个公开发布的闭源库,否则字段很容易在需要时转换为属性,并且对公共字段的非理性恐惧只是一些面向对象的我们最好摆脱这种教条。
这完全取决于版本控制和API稳定性.在版本1中没有区别 - 但是稍后,如果您决定需要在版本2中将此属性设置为某种类型的错误检查,则无需在任何地方更改API,无需更改代码,财产的定义.
建立一个领域没有错public.但是记住getter/setter用private字段创建并不是封装.IMO,如果你不关心a的其他功能Property,你也可以做到public.