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

时间:2008-12-18 19:59:51

标签: c# .net properties field

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

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;

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

11 个答案:

答案 0 :(得分:31)

我只会在公共字段是(静态)常量时公开它们 - 甚至那时我通常会使用属性。

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

即使是只读实例变量(如Result和Message)也应该封装在我视图的属性中。

有关详细信息,请参阅this article

答案 1 :(得分:17)

  

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

“不要。”另请参阅: Should protected attributes always be banned?涉及受保护的领域,但对于公共领域更是如此。

答案 2 :(得分:9)

使用属性。现在,C#很容易Automatic Properties

答案 3 :(得分:4)

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

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

答案 4 :(得分:3)

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

这是一篇很好的文章:

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

答案 5 :(得分:2)

我建议使用类似的东西:

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;
    }
}

这样,你不需要声明成员变量,让编译器为你工作!代码非常简洁,重构也很简单。

答案 6 :(得分:2)

在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中,字段与属性不同。

这个article(由其他人指出)解释了它的.NET方面。

答案 7 :(得分:1)

答案 8 :(得分:1)

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

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

最佳做法是始终使用“属性”在构造函数后访问您的字段。所以,如果您必须从课堂内访问您的房产,我会提出:

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; }
}

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

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

编辑:在根据问题中给出的内容阅读我做的代码之后,有一些错误,类名结果可能会抛出属性结果的错误,也就是我们的事实正在接收一个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; }
}

答案 9 :(得分:0)

我给出的答案是,属性对Refactor更友好。

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

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

答案 10 :(得分:0)

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

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

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