C# 字段和属性有什么区别?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/295104/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 22:01:12  来源:igfitidea点击:

What is the difference between a field and a property?

c#propertiesfield

提问by

In C#, what makes a field different from a property, and when should a field be used instead of a property?

在 C# 中,是什么使字段与属性不同,何时应该使用字段而不是属性?

采纳答案by Cory

Properties expose fields. Fields should (almost always) be kept private to a class and accessed via get and set properties. Properties provide a level of abstraction allowing you to change the fields while not affecting the external way they are accessed by the things that use your class.

属性公开字段。字段应该(几乎总是)对类保持私有,并通过 get 和 set 属性访问。属性提供了一个抽象级别,允许您更改字段,同时不影响使用您的类的事物访问它们的外部方式。

public class MyClass
{
    // this is a field.  It is private to your class and stores the actual data.
    private string _myField;

    // this is a property. When accessed it uses the underlying field,
    // but only exposes the contract, which will not be affected by the underlying field
    public string MyProperty
    {
        get
        {
            return _myField;
        }
        set
        {
            _myField = value;
        }
    }

    // This is an AutoProperty (C# 3.0 and higher) - which is a shorthand syntax
    // used to generate a private field for you
    public int AnotherProperty{get;set;} 
}

@Kent points out that Properties are not required to encapsulate fields, they could do a calculation on other fields, or serve other purposes.

@Kent 指出 Properties 不需要封装字段,它们可以对其他字段进行计算,或用于其他目的。

@GSS points out that you can also do other logic, such as validation, when a property is accessed, another useful feature.

@GSS 指出您还可以执行其他逻辑,例如在访问属性时进行验证,这是另一个有用的功能。

回答by danswain

Object orientated programming principles say that, the internal workings of a class should be hidden from the outside world. If you expose a field you're in essence exposing the internal implementation of the class. Therefore we wrap fields with Properties (or methods in Java's case) to give us the ability to change the implementation without breaking code depending on us. Seeing as we can put logic in the Property also allows us to perform validation logic etc if we need it. C# 3 has the possibly confusing notion of autoproperties. This allows us to simply define the Property and the C#3 compiler will generate the private field for us.

面向对象的编程原则说,类的内部工作应该对外界隐藏。如果你公开一个字段,你本质上就是在公开类的内部实现。因此,我们用属性(或 Java 的方法)包装字段,使我们能够在不破坏代码的情况下更改实现。看到我们可以在属性中放置逻辑也允许我们在需要时执行验证逻辑等。C# 3 具有可能令人困惑的自动属性概念。这允许我们简单地定义属性,C#3 编译器将为我们生成私有字段。

public class Person
{
   private string _name;

   public string Name
   {
      get
      {
         return _name;
      }
      set
      {
         _name = value;
      }
   }
   public int Age{get;set;} //AutoProperty generates private field for us
}

回答by Jonathan C Dickinson

If you are going to use thread primitives you are forced to use fields. Properties can break your threaded code. Apart from that, what cory said is correct.

如果您打算使用线程原语,您将被迫使用字段。属性可能会破坏您的线程代码。除此之外,科里说的是正确的。

回答by Jonathan C Dickinson

Properties encapsulate fields, thus enabling you to perform additional processing on the value to be set or retrieved. It is typically overkill to use properties if you will not be doing any pre- or postprocessing on the field value.

属性封装字段,从而使您能够对要设置或检索的值执行附加处理。如果您不会对字段值进行任何预处理或后处理,那么使用属性通常是过度的。

回答by Scott Wisniewski

Properties have the primary advantage of allowing you to change the way data on an object is accessed without breaking it's public interface. For example, if you need to add extra validation, or to change a stored field into a calculated you can do so easily if you initially exposed the field as a property. If you just exposed a field directly, then you would have to change the public interface of your class to add the new functionality. That change would break existing clients, requiring them to be recompiled before they could use the new version of your code.

属性的主要优点是允许您在不破坏对象的公共接口的情况下更改访问对象上数据的方式。例如,如果您需要添加额外的验证,或将存储的字段更改为计算的字段,如果您最初将该字段公开为属性,则可以轻松完成。如果您只是直接公开一个字段,那么您必须更改类的公共接口以添加新功能。该更改会破坏现有客户端,要求它们在使用新版本代码之前重新编译。

If you write a class library designed for wide consumption (like the .NET Framework, which is used by millions of people), that can be a problem. However, if you are writing a class used internally inside a small code base (say <= 50 K lines), it's really not a big deal, because no one would be adversely affected by your changes. In that case it really just comes down to personal preference.

如果您编写一个专为广泛使用而设计的类库(如被数百万人使用的 .NET Framework),这可能是一个问题。但是,如果您正在编写一个在小型代码库中内部使用的类(比如 <= 50 K 行),这真的没什么大不了的,因为没有人会受到您的更改的不利影响。在那种情况下,它真的只是归结为个人喜好。

回答by GurdeepS

Also, properties allow you to use logic when setting values.

此外,属性允许您在设置值时使用逻辑。

So you can say you only want to set a value to an integer field, if the value is greater than x, otherwise throw an exception.

所以你可以说你只想给一个整数字段设置一个值,如果该值大于x,否则抛出异常。

Really useful feature.

真正有用的功能。

回答by Rune Grimstad

In the background a property is compiled into methods. So a Nameproperty is compiled into get_Name()and set_Name(string value). You can see this if you study the compiled code. So there is a (very) small performance overhead when using them. Normally you will always use a Property if you expose a field to the outside, and you will often use it internally if you need to do validation of the value.

在后台,一个属性被编译成方法。所以一个Name属性被编译成get_Name()and set_Name(string value)。如果您研究编译后的代码,您可以看到这一点。因此,使用它们时有(非常)小的性能开销。通常,如果您将字段暴露给外部,您将始终使用属性,如果您需要对值进行验证,您通常会在内部使用它。

回答by Brian Rasmussen

Properties support asymmetric access, i.e. you can have either a getter and a setter or just one of the two. Similarly properties support individual accessibility for getter/setter. Fields are always symmetric, i.e. you can always both get and set the value. Exception to this is readonly fields which obviously cannot be set after initialization.

属性支持非对称访问,即您可以拥有一个 getter 和一个 setter,或者只有两者之一。类似的属性支持 getter/setter 的个人可访问性。字段始终是对称的,即您始终可以获取和设置值。对此的例外是只读字段,在初始化后显然不能设置。

Properties may run for a very long time, have side effects, and may even throw exceptions. Fields are fast, with no side effects, and will never throw exceptions. Due to side effects a property may return a different value for each call (as may be the case for DateTime.Now, i.e. DateTime.Now is not always equal to DateTime.Now). Fields always return the same value.

属性可能会运行很长时间,产生副作用,甚至可能引发异常。字段很快,没有副作用,永远不会抛出异常。由于副作用,属性可能会为每次调用返回不同的值(DateTime.Now 可能就是这种情况,即 DateTime.Now 并不总是等于 DateTime.Now)。字段总是返回相同的值。

Fields may be used for out / ref parameters, properties may not. Properties support additional logic – this could be used to implement lazy loading among other things.

字段可用于 out / ref 参数,属性则不可。属性支持额外的逻辑——这可用于实现延迟加载等。

Properties support a level of abstraction by encapsulating whatever it means to get/set the value.

属性通过封装获取/设置值的任何含义来支持抽象级别。

Use properties in most / all cases, but try to avoid side effects.

在大多数/所有情况下使用属性,但尽量避免副作用。

回答by Hans L?ken

An important difference is that interfaces can have properties but not fields. This, to me, underlines that properties should be used to define a class's public interface while fields are meant to be used in the private, internal workings of a class. As a rule I rarely create public fields and similarly I rarely create non-public properties.

一个重要的区别是接口可以有属性但没有字段。对我来说,这强调应该使用属性来定义类的公共接口,而字段则用于类的私有内部工作。通常我很少创建公共字段,同样我也很少创建非公共属性。

回答by Chris

I'll give you a couple examples of using properties that might get the gears turning:

我会给你几个使用可能让齿轮转动的属性的例子:

  • Lazy Initialization:If you have a property of an object that's expensive to load, but isn't accessed all that much in normal runs of the code, you can delay its loading via the property. That way, it's just sitting there, but the first time another module tries to call that property, it checks if the underlying field is null - if it is, it goes ahead and loads it, unknown to the calling module. This can greatly speed up object initialization.
  • Dirty Tracking:Which I actually learned about from my own questionhere on StackOverflow. When I have a lot of objects which values might have changed during a run, I can use the property to track if they need to be saved back to the database or not. If not a single property of an object has changed, the IsDirty flag won't get tripped, and therefore the saving functionality will skip over it when deciding what needs to get back to the database.
  • 延迟初始化如果您有一个对象的属性加载起来很昂贵,但在代码的正常运行中没有那么多访问,您可以通过属性延迟它的加载。这样,它只是坐在那里,但是当另一个模块第一次尝试调用该属性时,它会检查基础字段是否为空 - 如果是,则继续加载它,调用模块不知道。这可以大大加快对象初始化。
  • 脏跟踪:我实际上是从StackOverflow 上我自己的问题中了解到的。当我有很多在运行期间其值可能发生变化的对象时,我可以使用该属性来跟踪是否需要将它们保存回数据库。如果对象的单个属性没有更改,则 IsDirty 标志不会被触发,因此在决定需要返回数据库的内容时,保存功能将跳过它。