使用公共字段的最佳做法是什么?

当我写一个类时,我总是通过这样的公共属性公开私有字段:

private int _MyField; public int MyField { get{return _MyField; } 

什么时候可以公开这样的公共字段:

 public int MyField; 

我正在创建一个名为Result的结构,我的意图是这样做:

 public Result(bool result, string message) { Result = result; Message = message; } public readonly int Result; public readonly int Message; 

什么是最佳做法? 这样做好吗?

当它们是(静态)常量时,我​​只暴露公共字段 – 即便如此,我通常也会使用属性。

“常量”是指任何只读,不可变的值,而不仅仅是可以在C#中表示为“const”的值。

甚至readonly 实例变量(如Result和Message)也应该封装在我视图的属性中。

有关详细信息,请参阅此文章 。

使用公共字段的最佳做法是什么?

“不要。”另请参阅: 是否应始终禁止受保护的属性? 这涉及到受保护的领域,但对于公共领域来说更是如此。

使用属性。 现在C#有自动属性很容易!

最佳做法是出于多种原因使用属性。 首先,它将API与底层数据结构分离。 其次,绑定到对象的框架内置的任何内容都会对属性产生影响,而不是字段。

我相信还有更多的理由,但这两个似乎对我来说似乎已经足够了。

我认为最佳做法不是这样做。 除非你有一些极端的性能需求,你必须直接访问该领域,否则不要这样做。

这是一篇很好的文章:

http://csharpindepth.com/Articles/Chapter8/PropertiesMatter.aspx

我推荐使用类似的东西:

 public class Result{ public bool Result { get; protected set; } public string Message { get; protected set; } public Result(bool result, string message) { Result = result; Message = message; } } 

这样,您不需要声明成员变量,让编译器为您完成工作! 代码非常干净和简短,重构是轻而易举的。

在C风格的语言(如C#)中,您应该通过属性公开字段。 这也适用于VB.NET和其他.NET语言,以及它们共享相同的底层引擎。 这样做的主要原因是

公共MyField作为整数不等于公共属性MyField作为整数,它们在.NET下的所有情况下都没有相同的行为。

但是你可能会看到很多人继续公开领域。 其中一些是由于VB6如何处理COM。 在VB6中,Public MyField as Integer等同于Public Property MyField as Integer。 因为当它们都被翻译成COM类型库时,它们都以相同的方式实现。

这导致了VB6中许多奇怪的限制,而不是公共领域。 不在.NET和许多其他面向对象语言中的限制。 这些限制是在编译时捕获的,因此可以防止程序员在脚下射击。 如果你的课程在VB6中是私人的,那么这些限制中的一些,但不是全部,都得到了缓解。 一般规则是您只能将类和数据类型公开为公共字段。

VB6的遗留意味着有很多程序员不知道.NET存在差异。

因为.NET在这方面没有帮助我们,所以你需要采取传统步骤,确保所有字段都通过属性公开。 再次因为在.NET中,字段与Property不同。

本文 (由其他人指出)解释了它的.NET方面。

C#中的Field和Property之间有什么区别?

我想以你的方式回答你的问题。

Readonly不是在公共字段上只有get访问器的方法。 我主要在私有字段上使用readonly,我的私有字段只能从构造函数设置。 所以要理解一个readonly字段只能在一个构造函数中设置然后你只能访问它。

最佳实践是始终使用Properties在构造函数之后访问您的字段。 所以万一你必须从课堂内访问你的房产,我会把:

 private readonly int result; private readonly int message; public Result(bool result, string message) { this.result = result; this.message = message; } public int Result { get{ return result; } private set { result = value; } } public int Message { get{ return message; } private set { message = value; } } 

这样你只能读取结果和消息,并且仍然可以从类内部写入。

如果您使用inheritance,您可以根据需要设置保护集。

编辑 :在阅读我根据问题中给出的代码后,有一些错误,类名结果可能会抛出属性结果的错误,而且我们收到一个bool作为结果和字符串为在构造函数中的消息,但试图在int中发送它们肯定不起作用。 但是,对于它的价值来说,这是一个逻辑:

 private readonly bool result; private readonly string message; public Answer(bool result, string message) { this.result = result; this.message = message; } public bool Result { get{ return result; } private set { result = value; } } public string Message { get{ return message; } private set { message = value; } } 

我给出的答案是属性更加重构友好。

如果您有一个只读字段的程序集,则将它们更改为属性。 如果你有另一个我访问字段(现在属性)的程序集,它们将无法在没有编译的情况下工作。 就编译器而言,字段和属性并不相同。

回到重构,说你从一个属性开始。 现在您需要更改数据的来源(您将从另一个类访问它)。 如果您正在处理字段,那么您就如何实现这一点做出了一些艰难的决定。 属性更宽容 – 因为你可以在其中隐藏逻辑。

通常,如果某个类型将用作数据持有者,它应该是:

  1. 具有暴露字段的可变结构,如果每个字段将从类型的立场表现为值,并且任何字段值的任意组合将“有意义”。 请注意,如果字段的用途是保存相关对象的标识而不是内容,则保留对可变类类型的引用的字段可能有资格。 由于愚蠢的C#编译器会将`SomeThing.SomeStruct.SomeField = whatever`解释为`tempStruct = SomeThing.SomeStruct;而具有可变字段的结构声名狼借。 tempStruct.SomeField = what`而不发布诊断,但今天程序员没有理由担心古代编译器会做什么。
  2. 具有非公共字段的不可变类或结构,对于上述不适用的情况,以及必须重新生成整个数据项以改变其一个方面的情况,不会过于麻烦。
  3. 一个可变类,如果对它的引用不会在创建它的实体之外持久化(这样的引用通常不会暴露给外部代码)。 请注意,其他两个选项在可行时应该是非常优选的,因为使用可变类类型作为数据持有者的集合(与仅存储对象标识但不关心这些对象表示的集合相对)通常必须制作存储在集合中的任何对象的防御性副本,然后在每次读取对象时再制作一个防御性副本。 无论是可变的还是“不可变的”结构,只要它们被存储或从集合中读回,就必须被复制,但对于任何大小的结构 ,这些副本比使用可变类所需的防御副本更便宜。

如果没有使用可变类的实际替代方法,是否公开公共字段的问题取决于是否有任何可预见的类需要在属性设置器中包含validation逻辑,以及是否成员类型将是值类型或类类型。 如果BoundsRectangle类型的公共字段,则像SomeClass.Bounds.Width这样的表达式可以访问矩形的Width ,而无需访问任何其他成员。 相比之下,如果Bounds是一个属性 – 甚至是一个可变的属性 – 该表达式必须将Bounds所有四个成员复制到一个临时结构,然后访问它的Width字段。