为什么要使用字段而不是属性?

Mat*_*hew 36 c# coding-style field properties

我对C#很新,我认为属性是一件很棒的事情.事实上,如此精彩,我看不到使用字段的任何真正优势.即使对于私人领域,性能提供的灵活性和模块性似乎最多可以避免严重的麻烦,最糟糕的是根本没有效果.

我可以在字段中看到的唯一优势是您可以内联初始化它们.但是大多数时候,你想在构造函数中初始化它们.如果您不使用内联初始化,是否有任何理由不使用属性?

编辑:有些人提出需要使用字段备份属性(显式或自动).让我们澄清一下我的问题:除了备份属性之外,有没有理由使用字段?也就是说,有没有比这SomeType someField;更好的时间了SomeType SomeProperty { get; set; }

编辑2:DanM,Skurmedel和Seth都提供了非常有用的答案.我已经接受了DanM,因为它是最完整的,但如果有人将他们的回答总结为一个答案,我会很乐意接受它.

dev*_*xer 25

通常,属性需要一个支持字段,除非它们是简单的getter/setter"自动属性".

所以,如果你只是......

public string Name { get; set; } // automatic property
Run Code Online (Sandbox Code Playgroud)

......你不需要一个领域,我同意,没有理由拥有一个领域.

但是,如果你正在......

public string Name
{
    get { return _name; }
    set 
    {
       if (value = _name) return;
       _name = value;
       OnPropertyChange("Name");
    }
}
Run Code Online (Sandbox Code Playgroud)

......你需要那个_name支持领域.

对于不需要任何特殊get/set逻辑的私有变量,它实际上是一个判断调用,无论是私有自动属性还是只是一个字段.我通常做一个字段,然后,如果我需要它,protected或者public,我会将它改为自动属性.

更新

正如Yassir所指出的,如果你使用自动属性,那么幕后仍然会有一个潜伏的场地,这不是你实际需要输入的东西.因此,底线是:属性不存储数据,它们提供对数据的访问.字段是实际保存数据的内容.所以,即使你看不到它们,你也需要它们.

更新2

关于你修改过的问题......

有没有时间SomeType someField; 比较SomeType SomeProperty { get; set; }好吗?

......有一件事情会浮现在脑海中:如果你有一个私人领域,并且(根据私人领域的惯例),你可以打电话给它_name,并向你和任何阅读你的代码的人发出信号,表明你正在使用私人数据.另一方面,如果你把所有东西都作为属性,并且(根据属性的约定)调用你的私有属性Name,现在你不能只看变量并告诉它是私有数据.因此,仅使用属性会删除一些信息.我没有尝试过与所有房产合作来衡量这是否是关键信息,但肯定会丢失一些东西.

另一件事,更轻微的是,public string Name { get; set; }需要更多的打字(并且有点麻烦)private string _name.

  • 我认为海报的重点是:即使您给出的示例中的_name字段也可能是私有的自动实现属性.从理论上讲,你根本不需要了解这些字段,它们只是属性如何工作的实现细节,编译器可以完全隐藏它们作为实现细节,就像CPU寄存器一样. (5认同)

Set*_*eth 12

属性是一件很棒的事情 - 但是存在与属性访问相关的开销.不一定是问题,但需要注意的事项.

避免过度使用财产吸气剂和二传手

大多数人都没有意识到,在开销方面,属性getter和setter与方法类似; 它主要是区分它们的语法.除了字段访问之外不包含任何指令的非虚拟属性getter或setter将由编译器内联,但在许多其他情况下,这是不可能的.你应该仔细考虑你对财产的使用; 从类内部直接访问字段(如果可能),并且从不盲目地重复调用属性而不将值存储在变量中.总而言之,这并不意味着你应该使用公共领域!

资料来源:http://dotnet.sys-con.com/node/46342

  • "非虚拟属性getter或setter不包含除了字段访问之外的其他指令将由编译器内联"他所指的情况(私有自动实现属性)将属于此类别,因此不会影响性能这个. (8认同)

Jen*_*enk 12

在使用ref/out args时尝试使用Property:

someObject.SomeMethod(ref otherObject.SomeProperty);
Run Code Online (Sandbox Code Playgroud)

它不会编译.


Sku*_*del 10

如果你想拥有一些东西,readonly你几乎必须使用一个字段,因为没有办法告诉自动属性生成一个只读字段.

我经常这样做.

举例:

class Rectangle
{
   private readonly int _width;
   private readonly int _height;

   public Rectangle(int width, int height)
   {
      _width = width;
      _height = height;
   }

   public int Width { get { return _width; } }
   public int Height { get { return _height; } }
}
Run Code Online (Sandbox Code Playgroud)

这意味着Rectangle内部的任何内容都不能改变构造后的宽度或高度.如果一个人试图编译器会抱怨.

如果我使用私有setter的自动属性,编译器将不会保护我自己.

我看到的另一个原因是,如果一块数据不必暴露(停留private)为什么要将它作为财产?

  • C#6.0现在支持只读属性!`对象MyProp {get; 这个属性可以设置为内联(`object MyProp {get;} = ...`)或在构造函数中,但不在其他地方(就像只读字段一样). (10认同)

小智 5

我不明白你为什么要使用私有自动属性。有什么好处可以

private int Count {get; set;}
Run Code Online (Sandbox Code Playgroud)

超过

private int count
Run Code Online (Sandbox Code Playgroud)

  • 默认属性可以设置为虚拟的,以便可以覆盖它,并且您可以独立控制 get 和 set 访问(例如,使 get 访问器公开,使 set 访问器受保护)。如果您一开始不需要这些,但稍后可能需要它们怎么办?然后,您可以从字段开始,稍后使用属性,除非您通过反射访问字段或属性。所以……优势只是有时存在。 (4认同)
  • 还值得注意的是,如果您稍后因为需求发生变化而从字段转换为属性,则引用该字段的任何内容也必须重新编译。 (3认同)

Bil*_*llW 5

尽管我同意David Basarab声明中的“意图”:“没有理由公开展示字段”,但我想强调一点不同:

我将上面David的引言修改为:“没有理由公开公开……在类之外……除非有意识地选择将字段封装在Properties中,以严格控制访问。

属性不仅是“附加到” C#字段上的语法的“转折点”:它们是一种基本的语言功能,其设计基于以下充分的理由,包括:

  1. 控制在类之外公开和不公开的内容(封装,数据隐藏)

  2. 允许在访问或设置属性时执行某些操作:最好在属性“ get”和“ set”中表示的操作,而不是“提升”到外部定义的方法。

  3. 设计上的接口无法定义'fields :,但可以定义属性。

好的OO设计意味着有意识地选择“状态”:

  1. 局部变量字段:什么状态对方法是私有的,并且是瞬态的:局部变量通常仅在方法主体的范围内有效,甚至在“ for循环”之类的范围内有效。当然,您也可以将方法中的参数变量也视为“局部”。

  2. 类实例字段:什么状态是类专有的,并且对于类的每个实例具有独立的存在性,但是很可能需要在类中的多个位置使用。

  3. 静态实例字段:什么状态将仅是该类的属性,而与该类的实例数量无关。

  4. 状态故意并有意识地暴露在类的“外部”:关键思想是,在类和类的“消费者”所暴露的数据之间至少存在一个间接级别。当然,“暴露”的“反面”是有意识地隐藏(封装,隔离)实现代码。

    一种。通过公共财产:这里的所有其他答案都涵盖了这个方面

    b。通过索引器

    C。通过方法

    d。公共静态变量通常在实用程序类(通常是静态类)中找到。

建议您评论:关于“字段 ”的MSDN ... 关于属性的MSDN ... 关于索引器的MSDN