我们经常被告知,应该通过为类字段创建getter和setter方法(c#中的属性)来保护封装,而不是将字段暴露给外界。

但是很多时候,一个字段只是用来保存一个值,不需要任何计算来获取或设置。对于这些问题,我们都会做这个数字:

public class Book
{
    private string _title;

    public string Title
    {
          get => _title; 
          set => _title = value;
    }
}

好吧,我有一个忏悔,我不能忍受写所有这些(真的,不是必须写它,而是必须看它),所以我擅自使用了公共字段。

然后出现了c# 3.0,我看到他们添加了自动属性:

public class Book
{
    public string Title { get; set; } 
}

哪个更整洁,我很感激,但说真的,这和仅仅创建一个公共字段有什么不同呢?

public class Book
{
    public string Title;
}

当前回答

Trivial properties like these make me sad. They are the worst kind of cargo culting and the hatred for public fields in C# needs to stop. The biggest argument against public fields is future-proofing: If you later decide you need to add extra logic to the getter and setter, then you will have to do a huge refactor in any other code that uses the field. This is certainly true in other languages like C++ and Java where the semantics for calling a getter and setter method are very different from those for setting and getting a field. However, in C#, the semantics for accessing a property are exactly the same as those for accessing a field, so 99% of your code should be completely unaffected by this.

我所见过的一个将字段更改为属性的例子实际上是源代码级别的破坏性更改,如下所示:

    TryGetTitle(out book.Title); // requires a variable

对此,我要问,为什么TF要传递其他类的字段作为引用?依赖于它不是一个属性似乎是这里真正的编码失败。假设您可以直接写入另一个类中的数据,而您对此一无所知,这是一种糟糕的实践。制作你自己的局部变量和集书。标题就是这样的。任何做这种事情的代码都应该被打破。

我还看到了其他反对的观点:

Changing a field to a property breaks binary compatibility and requires any code that uses it to be recompiled: This is a concern iff you are writing code for distribution as a closed-source library. In that case, yes, make sure none of your user-facing classes have public fields and use trivial properties as needed. If however you are like 99% of C# developers and writing code purely for internal consumption within your project, then why is recompilation a big concern? Just about any other change you make is going to require recompilation too, and so what if it does? Last I checked, it is no longer 1995, we have fast computers with fast compilers and incremental linkers, even larger recompilations shouldn't need more than a few minutes, and it has been quite some time since I have been able to use "my code's compiling" as an excuse for swordfighting through the office. You can't databind against a variable: Great, when you need to do that, make it into a property. Properties have features that make them better for debugging like reflection and setting breakpoints: Great, one you need to use one of those things, make it into a property. When you're done debugging and ready to release, if you don't still need those functionalities, change it back into a field. Properties allow you to override behavior in derived classes: Great, if you are making a base class where you think such a scenario is likely, then make the appropriate members into properties. If you're not sure, leave it as a field and you can change it later. Yes, that will probably require some recompilation, but again, so what?

所以总的来说,是的,对于一些不重要的属性有一些合法的用途,但是除非你是在为公共发布制作一个闭源库,否则在需要的时候,字段很容易转换成属性,而对公共字段的非理性恐惧只是一些面向对象的教条,我们应该很好地摆脱它。

其他回答

如果稍后决定通过与集合或数据库进行比较来检查标题是否唯一,则可以在属性中执行该操作,而无需更改依赖于它的任何代码。

如果只使用公共属性,那么灵活性就会降低。

对我来说,使用属性时最重要的是在不破坏契约的情况下获得额外的灵活性,在我真正需要这种灵活性之前,自动生成是最有意义的。

在我前段时间遇到的一个相关问题中,有一个链接指向Jeff博客上的一篇文章,解释了一些不同之处。

属性与公共变量

反射在变量和属性上的工作方式不同,因此如果依赖于反射,则更容易使用所有属性。 你不能对变量进行数据绑定。 将变量更改为属性是破坏性的更改。例如: TryGetTitle (book.Title);//需要一个变量

对我来说,不使用公共字段的绝对原因是缺乏智能感知,显示引用:

字段不可用。

我发现非常有用的一件事,以及所有的代码和测试的原因是,如果它是一个属性和一个字段,Visual Studio IDE会显示一个属性的引用,而不是一个字段。

只是因为没有人提到:你不能在接口上定义字段。如果你必须实现一个定义属性的特定接口,自动属性有时是一个很好的特性。