简体   繁体   English

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

[英]Why ever use fields instead of properties?

I'm fairly new to C#, and I think properties are a wonderful thing. 我对C#很新,我认为属性是一件很棒的事情。 So wonderful, in fact, that I can't see any real advantage to using fields, instead. 事实上,如此精彩,我看不到使用字段的任何真正优势。 Even for private fields, it seems like the flexibility and modularity that properties offer can at best save you serious headaches, and at worst have no effect at all. 即使对于私人领域,性能提供的灵活性和模块性似乎最多可以避免严重的麻烦,最糟糕的是根本没有效果。

The only advantage I can see for fields is that you can initialize them inline. 我可以在字段中看到的唯一优势是您可以内联初始化它们。 But most of the time, you want to initialize them in the constructor, anyway. 但是大多数时候,你想在构造函数中初始化它们。 If you aren't using inline initialization, is there any reason not to use properties all the time? 如果您不使用内联初始化,是否有任何理由不使用属性?

Edit: Some people have brought up the need to back up properties with fields (either explicitly or automatically). 编辑:有些人提出需要使用字段备份属性(显式或自动)。 Let clarify my question: Is there any reason to use fields except to back up properties ? 让我们澄清一下我的问题: 除了备份属性之外,有没有理由使用字段? Ie, is there any time that SomeType someField; 即, SomeType someField;有没有时间SomeType someField; is preferable to SomeType SomeProperty { get; set; } 优于SomeType SomeProperty { get; set; } SomeType SomeProperty { get; set; } SomeType SomeProperty { get; set; } ? SomeType SomeProperty { get; set; }

Edit 2: DanM, Skurmedel, and Seth all gave really useful answers. 编辑2:DanM,Skurmedel和Seth都提供了非常有用的答案。 I've accepted DanM's, as it is the most complete, but if someone were to summarize their responses into a single answer, I'd be happy to accept it. 我已经接受了DanM,因为它是最完整的,但如果有人将他们的回答总结为一个答案,我会很乐意接受它。

Typically, properties need a backing field unless they are simple getter/setter "automatic properties". 通常,属性需要一个支持字段,除非它们是简单的getter / setter“自动属性”。

So, if you're just doing... 所以,如果你只是......

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

...you don't need a field, and I agree, no reason to have one. ......你不需要一个领域,我同意,没有理由拥有一个领域。

However, if you're doing... 但是,如果你正在......

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

...you need that _name backing field. ...你需要_name支持字段。

For private variables that don't require any special get/set logic, it's really a judgment call whether to do a private automatic property or just a field. 对于不需要任何特殊get / set逻辑的私有变量,它实际上是一个判断调用,无论是私有自动属性还是只是一个字段。 I usually do a field, then, if I need it to be protected or public , I will change it to an automatic property. 我通常做一个字段,然后,如果我需要protectedpublic ,我会将其更改为自动属性。

Update 更新

As noted by Yassir, if you use automatic properties, there's still a field lurking behind the scenes, it's just not something you actually have to type out. 正如Yassir所指出的,如果你使用自动属性,那么幕后仍然会有一个潜伏的场地,这不是你实际需要输入的东西。 So, the bottom line is: properties don't store data, they provide access to data. 因此,底线是:属性不存储数据,它们提供对数据的访问。 Fields are what actually hold the data. 字段是实际保存数据的内容。 So, you need them even if you can't see them. 所以,即使你看不到它们,你也需要它们。

Update 2 更新2

Regarding your revised question... 关于你修改过的问题......

is there any time that SomeType someField; 有没有时间SomeType someField; is preferable to SomeType SomeProperty { get; set; } 优于SomeType SomeProperty { get; set; } SomeType SomeProperty { get; set; } SomeType SomeProperty { get; set; } ? SomeType SomeProperty { get; set; }

...one thing that comes to mind: If you have a private field, and (according to convention for private fields) you call it _name , that signals to you and anyone reading your code that you are working directly with private data. ...有一件事情会浮现在脑海中:如果您有一个私有字段,并且(根据私有字段的惯例),您将其称为_name ,它会向您和正在阅读您的代码的任何人发出信号,表明您正在使用私有数据。 If, on the other hand, you make everything a property, and (according to convention for properties) call your private property Name , now you can't just look at the variable and tell that it is private data. 另一方面,如果你把所有东西都作为属性,并且(根据属性的约定)调用你的私有属性Name ,现在你不能只看变量并告诉它是私有数据。 So, using only properties strips away some information. 因此,仅使用属性会删除一些信息。 I haven't tried working with all properties to gauge whether that is crucial information, but something is definitely lost. 我没有尝试过与所有房产合作来衡量这是否是关键信息,但肯定会丢失一些东西。

Another thing, more minor, is that public string Name { get; set; } 另一个更小的问题是public string Name { get; set; } public string Name { get; set; } public string Name { get; set; } requires more typing (and is a little messier) than private string _name . public string Name { get; set; }需要更多的输入(并且是有点混乱),比private string _name

Properties are a wonderful thing -- but there is overhead associated with property access. 属性是一件很棒的事情 - 但是存在与属性访问相关的开销。 Not necessarily a problem, but something to be aware of. 不一定是问题,但需要注意的事项。

Avoiding Overuse of Property Getters and Setters 避免过度使用财产吸气剂和二传手

Most people don't realize that property getters and setters are similar to methods when it comes to overhead; 大多数人都没有意识到,在开销方面,属性getter和setter与方法类似; it's mainly syntax that differentiates them. 它主要是区分它们的语法。 A non-virtual property getter or setter that contains no instructions other than the field access will be inlined by the compiler, but in many other cases, this isn't possible. 除了字段访问之外不包含任何指令的非虚拟属性getter或setter将由编译器内联,但在许多其他情况下,这是不可能的。 You should carefully consider your use of properties; 你应该仔细考虑你对财产的使用; from inside a class, access fields directly (if possible), and never blindly call properties repeatedly without storing the value in a variable. 从类内部直接访问字段(如果可能),并且从不盲目地重复调用属性而不将值存储在变量中。 All that said, this doesn't mean that you should use public fields! 总而言之,这并不意味着你应该使用公共领域!

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

Just try using a Property when using ref/out args: 在使用ref / out args时尝试使用Property:

someObject.SomeMethod(ref otherObject.SomeProperty);

It won't compile. 它不会编译。

If you want to have something readonly you pretty much have to use a field as there is no way to tell an automatic property to generate a read-only field. 如果你想要readonly一些东西,你几乎必须使用一个字段,因为没有办法告诉自动属性生成一个只读字段。

I do this quite often. 我经常这样做。

Contrived example: 举例:

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

This means nothing inside of Rectangle can alter the width or height after construction. 这意味着Rectangle内部的任何内容都不能改变构造后的宽度或高度。 If one tries to the compiler will complain. 如果一个人试图编译器会抱怨。

If I instead had used an automatic property with a private setter the compiler wouldn't protect me from myself. 如果我使用私有setter的自动属性,编译器将不会保护我自己。

Another reason I see is, if a piece of data doesn't have to be exposed (stay private ) why make it a property? 我看到的另一个原因是,如果不需要公开一些数据(保持private ),为什么要将其作为财产?

While I agree with what I perceive as the "intent" in David Basarab's statement : "There is no reason to publicly expose fields," I'd like to add a slightly different emphasis : 虽然我同意我认为大卫·巴萨拉布的声明中的“意图”:“没有理由公开曝光字段,”我想补充一点略有不同:

I'd modify the quote from David above to read : "There is no reason to publicly expose fields ... outside a class ... except through the conscious choice of encapsulating the fields in Properties through which access is rigorously controlled. 我将以上大卫的引用修改为:“除了通过有意识地选择封装严格控制访问的属性中的字段之外,没有理由公开暴露字段......在类之外......

Properties are not simply a "veneer" of syntax over Fields "tacked onto" C# : they are a fundamental language feature designed for good reasons including : 字段不仅仅是字段“贴在”C#上的“单板”:它们是一个基本的语言功能,其设计理由很充分,包括:

  1. controlling what is exposed and not exposed outside classes (encapsulation, data hiding) 控制暴露的内容而不暴露在类外(封装,数据隐藏)

  2. allowing certain actions to be performed when a Property is accessed or set : actions that are best expressed in the Property 'get and 'set, rather than being "elevated" to externally defined methods. 允许在访问或设置属性时执行某些操作:最好在属性“获取和”设置中表达的操作,而不是“提升”到外部定义的方法。

  3. Interfaces by design cannot define 'fields : but can define Properties. 按设计的接口不能定义'字段:但可以定义属性。

Good OO Design means making conscious choices about "state" : 良好的OO设计意味着对“状态”进行有意识的选择:

  1. local variable fields : what state is private to a method and transient : local variables typically only valid within the scope of a method body, or even with as "narrow a lifespan" as within the scope of something like a 'for loop. 局部变量字段:什么状态是方法和瞬态的私有状态:局部变量通常仅在方法体的范围内有效,或者甚至在“for循环”范围内具有“缩短生命周期”。 Of course you can regard parameter variables in a method as "local" also. 当然,您也可以将方法中的参数变量视为“本地”。

  2. class instance fields : what state is private to a class, and has independent existence for each instance of a class, but is most likely required to be used in several places in the class. 类实例字段:什么状态是类的私有状态,并且对于类的每个实例都是独立存在的,但很可能需要在类的多个位置使用。

  3. static instance fields : what state will be a property of the class only, independent of the number of instances of the class. 静态实例字段:什么状态只是类的属性,与类的实例数无关。

  4. state deliberately and consciously exposed "outside" the class : the key idea being that there is at least one level of indirection interposed between the class and "consumers" of the data the class exposes. 故意并有意识地暴露出类“外部”:关键的想法是在类和本类公开的数据的“消费者”之间插入至少一个间接层。 The "flip side" of "exposure" is, of course, the conscious intention of hiding (encapsulating, isolating) implementation code. 当然,“曝光”的“反面”是隐藏(封装,隔离)实现代码的意图。

    a. 一个。 via public properties : all aspects of this well-covered in all the other answers here 通过公共财产:这里所有其他答案都涵盖了这方面的所有方面

    b. via indexers 通过索引器

    c. C。 via methods 通过方法

    d. d。 public static variables are usually found in utility classes, which are often static classes. 公共静态变量通常位于实用程序类中,通常是静态类。

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

I don't see why you'd use private autoproperties. 我不明白你为什么要使用私人autoproperties。 What advantage is there to 那有什么好处

private int Count {get; set;}

over 过度

private int count

There is no reason to publicly expose fields. 没有理由公开曝光字段。

If you public expose a field you can't change the source of the information, from inline defination to configuration file without refactoring.\\ 如果您公开公开某个字段,则无法更改信息来源,从内联定义到配置文件而不进行重构。

You could use a field to hide internal data. 您可以使用字段隐藏内部数据。 I rarely favor that, I only use fields when I am doing something to hide publicly and using it in a property. 我很少赞成这一点,当我做一些公开隐藏并在房产中使用它时,我只使用字段。 (ie I am not using Automatic property generation) (即我没有使用自动属性生成)

Fields are the only place you can store state. 字段是您可以存储州的唯一地方。 Properties are actually just a pair of methods with special syntax that allows them to be mapped to the get or set method depending on how they're being used: if a property modifies or accesses state, that state still has to be stored in a field. 属性实际上只是一对具有特殊语法的方法,允许它们根据它们的使用方式映射到get或set方法:如果属性修改或访问状态,该状态仍然必须存储在字段中。

You don't always see the fields. 你并不总是看到这些字段。 With C# 3 automatic properties, the field is created for you by the compiler. 使用C#3自动属性,编译器将为您创建该字段。 But it's still there. 但它仍然存在。 Furthermore, automatic properties have some significant limitations (eg no INotifyPropertyChanged support, no business logic in setters) that mean they're often inappropriate, and you need to create an explicit field and a manually defined property anyway. 此外,自动属性具有一些显着的局限性(例如,没有INotifyPropertyChanged支持,在setter中没有业务逻辑),这意味着它们通常是不合适的,并且您无论如何都需要创建显式字段和手动定义的属性。

As per David's answer , you're right if you're talking about an API: you almost never want to make the internal state (fields) part of the API. 根据David的回答 ,如果您正在讨论API,那么您就是对的:您几乎从不想让内部状态(字段)成为API的一部分。

The syntax for fields is a lot quicker to write than for properties, so when it's safe to use a field (private to the class) why not use it and save that extra typing? 字段的语法比写入属性要快得多,所以当使用字段(对类私有)时,为什么不使用它并保存额外的输入呢? If auto-implemented properties had the nice short concise syntax and you had to do extra work to make a plain old field, people might just start use properties instead. 如果自动实现的属性具有简洁的简洁语法,并且您不得不做额外的工作来创建一个普通的旧字段,那么人们可能只是开始使用属性。 Also, it's a convention now in C#. 此外,它现在是C#的惯例。 That's how people think, and it's what they expect to see in code. 这就是人们的思考方式,也是他们期望在代码中看到的东西。 If you do something different form the normal, you will confuse everyone. 如果你做了与平常不同的事情,你会混淆每个人。

But you could ask why the syntax for fields doesn't create an auto-implemented property instead of a field, so you get the best of both worlds - properties everywhere and a concise syntax. 但是你可以问为什么字段的语法不会创建一个自动实现的属性而不是一个字段,所以你可以充分利用这两个世界 - 各地的属性和简洁的语法。

There's a very simple reason why we still need to have explicit fields: 有一个非常简单的原因,我们仍然需要有明确的字段:

C# 1.0 didn't have all these nice features that we have now, so fields were a fact of life - you couldn't really live without them. C#1.0没有我们现在拥有的所有这些优秀功能,因此字段是生活中的事实 - 如果没有它们,你就无法生存。 Lots and lots of code relies on fields and properties being visibly different things. 许多代码依赖于字段和属性是明显不同的东西。 It simply cannot be changed now without breaking tons of code. 在不破坏大量代码的情况下,它现在无法更改。

I would suspect also that there are performance implications, but perhaps that can be solved by the jitter. 我还怀疑存在性能影响,但也许可以通过抖动来解决。

So we're stuck with fields forever, and since they're there and they've taken the best syntax, it makes sense to use them when it's safe to do so. 所以我们永远坚持使用字段,因为它们在那里并且它们采用了最好的语法,所以在安全的情况下使用它们是有意义的。

Fields and properties are not interchangeable. 字段和属性不可互换。 I guess what you're saying is accessing private fields through private properties. 我猜你所说的是通过私有财产访问私人领域。 I do this when it makes sense but for the most part, it's not necessary. 我这样做是有意义的,但在大多数情况下,没有必要。 The JIT optimizer will inline access to a private field through a private property in most cases anyway. 在大多数情况下,JIT优化器将通过私有属性内联访问私有字段。 And wrapping a private field in a private property is not considered a breaking change anyway since private members are not a part of your interface. 由于私有成员不是您的界面的一部分,因此将私有字段包装在私有财产中不会被视为重大变更。

Personally, I would never expose any protected/public instance fields. 就个人而言,我永远不会暴露任何受保护/公共实例字段。 It's generally acceptable though to expose a public static field with a readonly modifier as long as the field type is itself immutable. 虽然只要字段类型本身是不可变的,但通常使用只读修饰符公开公共静态字段是可以接受的。 This is often seen with SomeStruct.Empty static fields. 这通常出现在SomeStruct.Empty静态字段中。

As others have noted, you will need a private backing field for properties anyway. 正如其他人所指出的那样,无论如何你都需要一个私人支持领域。

Also there is a speed advantage in using fields over properties. 在属性上使用字段也有速度优势。 In 99.99 % of the cases it won't matter. 在99.99%的情况下,这无关紧要。 But in some it might. 但有些可能会。

Speed. 速度。 If a field gets set or read billions of times over the course of a simulation then you want to use a field and not a property to avoid the overhead och a sub routine call. 如果在模拟过程中字段被设置或读取数十亿次,那么您希望使用字段而不是属性来避免子例程调用的开销。 Conforming to OO (DDD?) as far as possible, in these instances, I'd recommend resorting to fields only in class dedicated to representing some sort of "value" like person. 尽可能符合OO(DDD?),在这些情况下,我建议仅在专门用于表示某种“价值”的类中使用字段。 Logic should be kept to a minimum. 逻辑应该保持在最低限度。 Rather, have a personcreator or a personservicer. 相反,有一个人或者一个人。

But if you have these issues then you're probably not programming c++ and not c#, aren't you? 但如果你有这些问题,那么你可能不是编程c ++而不是c#,不是吗?

There are several good (partial) answers by @Seth (fields perform better, so in a private context you might as well use that to your benefit when it makes sense), @Skurmedel (fields can be readonly), @Jenk (fields can be used for ref/out). @Seth有几个好的(部分)答案(字段表现更好,因此在私人环境中你可能会在有意义的时候使用它),@ Skurmedel(字段可以只读),@ Jenk(字段可以用于ref / out)。 But I'd like to add one more: 但是我想补充一点:

You can use the streamlined initialization syntax for setting the value of a field, but not a property. 您可以使用简化的初始化语法来设置字段的值,但不能使用属性。 ie: 即:

private int x = 7;

vs 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