我们经常被告知,应该通过为类字段创建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;
}

当前回答

一个经常被忽视的巨大差异,在任何其他答案中都没有提到:覆盖。可以将属性声明为virtual并覆盖它们,但不能对公共成员字段执行相同的操作。

其他回答

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

One thing you can do with Fields but not with Properties (or didn't used to be able to ... I'll come to that in a moment) is that Fields can be designated as readonly whereas Properties cannot. So Fields give you a clear way of indicating your intention that a variable is there to be set (from within the constructor) at object-instantiation time only and should not be changed thereafter. Yes, you can set a Property to have a private setter, but that just says "this is not to be changed from outside the class", which is not the same as "this is not to be changed after instantiation" - you can still change it post-instantiation from within the class. And yes you can set the backing field of your property to be readonly, but that moves post-instantiation attempts to change it to being run-time errors rather than compile-time errors. So readonly Fields did something useful which Properties cannot.

然而,这在c# 9中发生了变化,我们得到了下面这些有用的属性语法:

public string Height { get; init; }

它说“这个可以从类外使用,但它只能在对象初始化时设置”,因此Fields的只读优势消失了。

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

我的丈夫做了一些调查

验证。 允许重写访问器以更改属性的行为。 调试的目的。通过在访问器中设置断点,我们将能够知道属性何时发生变化以及发生了什么变化。 我们可以有一个现场布景。例如,public set()和private get()。对于公共字段,这是不可能的。

它确实给了我们更多的可能性和可扩展性。

忽略API问题,我发现关于使用属性最有价值的事情是调试。

CLR调试器不支持数据断点(大多数本机调试器支持)。因此,不可能在类的特定字段的读或写上设置断点。这在某些调试场景中非常有限。

因为属性是作为非常薄的方法实现的,所以可以在其值的读写上设置断点。这让它们在田野上占据了很大的优势。