繁体   English   中英

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

[英]Why ever use fields instead of properties?

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

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

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

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

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

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

public string Name { get; set; } // automatic property

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

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

public string Name
{
    get { return _name; }
    set 
    {
       if (value = _name) return;
       _name = value;
       OnPropertyChange("Name");
    }
}

...你需要_name支持字段。

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

更新

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

更新2

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

有没有时间SomeType someField; 优于SomeType SomeProperty { get; set; } SomeType SomeProperty { get; set; } SomeType SomeProperty { get; set; }

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

另一个更小的问题是public string Name { get; set; } public string Name { get; set; } public string Name { get; set; }需要更多的输入(并且是有点混乱),比private string _name

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

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

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

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

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

someObject.SomeMethod(ref otherObject.SomeProperty);

它不会编译。

如果你想要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; } }
}

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

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

我看到的另一个原因是,如果不需要公开一些数据(保持private ),为什么要将其作为财产?

虽然我同意我认为大卫·巴萨拉布的声明中的“意图”:“没有理由公开曝光字段,”我想补充一点略有不同:

我将以上大卫的引用修改为:“除了通过有意识地选择封装严格控制访问的属性中的字段之外,没有理由公开暴露字段......在类之外......

字段不仅仅是字段“贴在”C#上的“单板”:它们是一个基本的语言功能,其设计理由很充分,包括:

  1. 控制暴露的内容而不暴露在类外(封装,数据隐藏)

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

  3. 按设计的接口不能定义'字段:但可以定义属性。

良好的OO设计意味着对“状态”进行有意识的选择:

  1. 局部变量字段:什么状态是方法和瞬态的私有状态:局部变量通常仅在方法体的范围内有效,或者甚至在“for循环”范围内具有“缩短生命周期”。 当然,您也可以将方法中的参数变量视为“本地”。

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

  3. 静态实例字段:什么状态只是类的属性,与类的实例数无关。

  4. 故意并有意识地暴露出类“外部”:关键的想法是在类和本类公开的数据的“消费者”之间插入至少一个间接层。 当然,“曝光”的“反面”是隐藏(封装,隔离)实现代码的意图。

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

    通过索引器

    C。 通过方法

    d。 公共静态变量通常位于实用程序类中,通常是静态类。

建议你回顾: MSDN on'Fields ... MSDN on Properties ... MSDN on Indexers

我不明白你为什么要使用私人autoproperties。 那有什么好处

private int Count {get; set;}

过度

private int count

没有理由公开曝光字段。

如果您公开公开某个字段,则无法更改信息来源,从内联定义到配置文件而不进行重构。

您可以使用字段隐藏内部数据。 我很少赞成这一点,当我做一些公开隐藏并在房产中使用它时,我只使用字段。 (即我没有使用自动属性生成)

字段是您可以存储州的唯一地方。 属性实际上只是一对具有特殊语法的方法,允许它们根据它们的使用方式映射到get或set方法:如果属性修改或访问状态,该状态仍然必须存储在字段中。

你并不总是看到这些字段。 使用C#3自动属性,编译器将为您创建该字段。 但它仍然存在。 此外,自动属性具有一些显着的局限性(例如,没有INotifyPropertyChanged支持,在setter中没有业务逻辑),这意味着它们通常是不合适的,并且您无论如何都需要创建显式字段和手动定义的属性。

根据David的回答 ,如果您正在讨论API,那么您就是对的:您几乎从不想让内部状态(字段)成为API的一部分。

字段的语法比写入属性要快得多,所以当使用字段(对类私有)时,为什么不使用它并保存额外的输入呢? 如果自动实现的属性具有简洁的简洁语法,并且您不得不做额外的工作来创建一个普通的旧字段,那么人们可能只是开始使用属性。 此外,它现在是C#的惯例。 这就是人们的思考方式,也是他们期望在代码中看到的东西。 如果你做了与平常不同的事情,你会混淆每个人。

但是你可以问为什么字段的语法不会创建一个自动实现的属性而不是一个字段,所以你可以充分利用这两个世界 - 各地的属性和简洁的语法。

有一个非常简单的原因,我们仍然需要有明确的字段:

C#1.0没有我们现在拥有的所有这些优秀功能,因此字段是生活中的事实 - 如果没有它们,你就无法生存。 许多代码依赖于字段和属性是明显不同的东西。 在不破坏大量代码的情况下,它现在无法更改。

我还怀疑存在性能影响,但也许可以通过抖动来解决。

所以我们永远坚持使用字段,因为它们在那里并且它们采用了最好的语法,所以在安全的情况下使用它们是有意义的。

字段和属性不可互换。 我猜你所说的是通过私有财产访问私人领域。 我这样做是有意义的,但在大多数情况下,没有必要。 在大多数情况下,JIT优化器将通过私有属性内联访问私有字段。 由于私有成员不是您的界面的一部分,因此将私有字段包装在私有财产中不会被视为重大变更。

就个人而言,我永远不会暴露任何受保护/公共实例字段。 虽然只要字段类型本身是不可变的,但通常使用只读修饰符公开公共静态字段是可以接受的。 这通常出现在SomeStruct.Empty静态字段中。

正如其他人所指出的那样,无论如何你都需要一个私人支持领域。

在属性上使用字段也有速度优势。 在99.99%的情况下,这无关紧要。 但有些可能会。

速度。 如果在模拟过程中字段被设置或读取数十亿次,那么您希望使用字段而不是属性来避免子例程调用的开销。 尽可能符合OO(DDD?),在这些情况下,我建议仅在专门用于表示某种“价值”的类中使用字段。 逻辑应该保持在最低限度。 相反,有一个人或者一个人。

但如果你有这些问题,那么你可能不是编程c ++而不是c#,不是吗?

@Seth有几个好的(部分)答案(字段表现更好,因此在私人环境中你可能会在有意义的时候使用它),@ Skurmedel(字段可以只读),@ Jenk(字段可以用于ref / out)。 但是我想补充一点:

您可以使用简化的初始化语法来设置字段的值,但不能使用属性。 即:

private int x = 7;

VS

private int x { get; set; }

// This must go in the constructor, sometimes forcing you to create 
// a constructor that has no other purpose.
x = 7;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM