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

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

其他回答

公开一个字段并没有什么错。但是请记住,使用私有字段创建getter/setter不是封装。在我看来,如果你不关心物业的其他功能,你不妨将其公开。

自动实现属性相对于公共字段的另一个优点是,您可以将set访问器设置为私有或受保护的,从而为定义它的对象类提供比公共字段更好的控制。

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

我的丈夫做了一些调查

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

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

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?

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