为什么使用公共变量?

时间:2009-11-23 00:11:43

标签: c# variables access-modifiers

变量,方法和类可以获得各种安全级别。 从我的C#经验来看,有:

  

公共
  内部
  保护
  受保护的内部
  私人

现在,我理解使用方法和类私有,或内部或受保护,但变量怎么样?即使我将变量设为私有,我也可以使用Property从不同的类中调用它。

我一直认为属性是最好的做法。因此,如果我可以使用它,我不需要通过实例直接调用变量。

有没有理由不将变量设为私有?

编辑:我看到有些人在讨论属性,就好像它们只是Glorified public variables

快速提醒:公共变量只返回它们的值。有了属性,您可以做更多。例如:

public int AmountOfBooks{
  get {
    //code to check certain conditions
    //maybe trigger an event while we're at it.
    //and a few conditionals.
    return this.amountOfBooks;
  }

  set {
    //a few conditionals
    //maybe trigger an event
    this.amountOfBooks = value;
    //and I can do even more... I think, never tried this.
  }
}

那些读过我个人资料的人都知道我是学生。使用属性作为“荣耀的公共变量”是我看到许多同学所做的事情。告诉他们可以做到这一点时最常见的回答是:“这是允许的吗?”

8 个答案:

答案 0 :(得分:14)

当然,在某些情况下,拥有公共领域是有意义的。例如,如果您要创建一个仅用于与现有非托管win32 API互操作的结构。

但是,如果要构建常规托管对象模型,最佳做法是将对象的属性建模为属性,并使用字段作为私有实现公开公开功能的机制。

更新:我将借此机会指出,我们已经尝试在C#3.0中轻松编写一个只访问后备存储的属性:

public int Foo { get; set; }

完全相同
private int _Foo;
public int Foo { get { return _Foo; } set { _Foo = value; } }

但更短更容易阅读。当然,如果您需要在以后使用后备存储将其扩展为长格式,那么这样做并不是一个重大改变。

你也可以这样做:

public int Foo { get; private set; }

如果你想为类/结构之外的代码创建一个只读的属性。

答案 1 :(得分:6)

如果在设置或获取变量时需要执行任何代码,或者如果在将来需要添加此类代码时,如果涉及API中存在任何不兼容的更改,则属性是最佳实践。< / p>

由于后一条款,在语言中“抢先”使用访问器很可能是有意义的,否则需要进行这种不兼容的更改(最着名的例子是getThis / setThis约定。 Java的)!

但是当你的语言允许你从公共变量切换到属性时,反之亦然,而不会在API中发生任何不兼容的更改(例如C#,Ruby,Python,...),当公众传播总体样板时很愚蠢访问器(getter和setter)除了复制到私有变量之外什么都不做 - 即使你确定你的编译器可以优化它们,这样的样板访问器只是无用地膨胀源,并浪费了一个重要的设计特性,这是什么的一部分使这些语言很好; - )

答案 2 :(得分:4)

在我的脑海中,我可以想到两个我会使用公共字段的地方

  1. 发布常量或只读 装配消费者的价值
  2. 我被迫部分地被迫 基础设施(例如工作流程) 基础)

答案 3 :(得分:0)

例如,如果您有一个具有属性id_code的类。

如果属性是公共的,我可以使用任何类型的值设置此变量。

如果您将此id_code设为私有并且您创建了一个设置它的方法,则可以制定有关id_code格式的规则。 所以方法:

public setIdCode(String id) {
    my_attribute_id_code = "000"+id;
}

这是第一个简单的例子。

答案 4 :(得分:0)

是。例如,将字段标记为受保护允许它由派生类直接使用,派生类仍然在概念上维护面向对象的哲学。

一般来说,你是对的。通常最好将类的字段标记为私有,并将必要的字段作为属性公开。这有利于封装,字段验证和代码维护等工作。

答案 5 :(得分:0)

在某些情况下,字段的处理方式与属性不同。标准序列化格式化程序(BinaryFormatter和SoapFormatter)将序列化字段,但不会序列化属性。有时可能需要控制类型的序列化。

答案 6 :(得分:0)

尚未提及的两个原因:

  1. 字段可以作为ref参数直接传递给方法。例如,可以以线程安全的方式调用字段上的“Interlocked.Increment”(如果该字段的其他用户也使用“Interlocked”例程来访问它)。将属性复制到局部变量,通过引用传递该变量,然后将变量复制回属性将产生不同的语义。
  2. 结构类型的字段可以比结构类型的属性更有效地访问和操作。实际上,许多与可变或大型结构相关的“问题”和低效率实际上源于这样一个事实,即属性假装是变量,但实际上并非如此。

这并不意味着将事物暴露为属性而不是字段没有优势,但字段确实具有明显的优势。

答案 7 :(得分:-2)

如果您的财产说Status具有性质:
public int Status {get; set;}

有些人可能会使用:
public int Status;