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


当前回答

基本区别和一般区别是:

领域

始终给予get和set访问权限不会造成副作用(引发异常、调用方法、更改字段(获取/设置的字段除外)等)

财产

并非总是同时提供get和set访问权限CAN导致副作用

其他回答

财产支持非对称访问,即您可以有getter和setter,也可以只有这两者之一。类似地,财产支持getter/setter的单独可访问性。字段始终是对称的,即您始终可以获取和设置值。例外情况是只读字段,在初始化后显然无法设置。

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

字段可以用于out/ref参数,财产则不能。财产支持额外的逻辑–这可以用于实现延迟加载等。

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

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

当你有一节课是“汽车”时。财产包括颜色、形状。。

其中as字段是在类范围内定义的变量。

由于他们中的许多人已经解释了财产和Field的技术优缺点,现在是时候进入实时示例了。

1.财产允许您设置只读访问级别

考虑dataTable.Rows.Count和dataTable.Column[i].Caption的情况。它们来自dataTable类,对我们来说都是公共的。对它们的访问级别的不同之处在于,我们不能将值设置为dataTable.Rrows.Count,但我们可以读写dataTable.Colomn[i].Taption。这可以通过Field实现吗?不这只能通过财产完成。

public class DataTable
{
    public class Rows
    {       
       private string _count;        

       // This Count will be accessable to us but have used only "get" ie, readonly
       public int Count
       {
           get
           {
              return _count;
           }       
       }
    } 

    public class Columns
    {
        private string _caption;        

        // Used both "get" and "set" ie, readable and writable
        public string Caption
        {
           get
           {
              return _caption;
           }
           set
           {
              _caption = value;
           }
       }       
    } 
}

2.PropertyGrid中的财产

您可能在Visual Studio中使用了Button。它的财产显示在PropertyGrid中,如Text、Name等。当我们拖放按钮时,当我们单击财产时,它将自动找到类button并过滤财产,并在Property Grid中显示该类(其中PropertyGrid不会显示Field,即使它们是公共的)。

public class Button
{
    private string _text;        
    private string _name;
    private string _someProperty;

    public string Text
    {
        get
        {
           return _text;
        }
        set
        {
           _text = value;
        }
   } 

   public string Name
   {
        get
        {
           return _name;
        }
        set
        {
           _name = value;
        }
   } 

   [Browsable(false)]
   public string SomeProperty
   {
        get
        {
           return _someProperty;
        }
        set
        {
           _someProperty= value;
        }
   } 

在PropertyGrid中,将显示财产Name和Text,但不显示SomeProperty。为什么?因为财产可以接受属性。如果[可浏览(false)]为false,则不会显示。

3.可以在财产中执行语句

public class Rows
{       
    private string _count;        


    public int Count
    {
        get
        {
           return CalculateNoOfRows();
        }  
    } 

    public int CalculateNoOfRows()
    {
         // Calculation here and finally set the value to _count
         return _count;
    }
}

4.绑定源中只能使用财产

绑定源帮助我们减少代码行数。BindingSource不接受字段。为此,我们应该使用财产。

5.调试模式

考虑我们使用Field来保存值。在某些时候,我们需要调试并检查该字段的值在哪里变为空。当代码行数超过1000行时,这将很难做到。在这种情况下,我们可以使用Property,并可以在Property中设置调试模式。

   public string Name
   {
        // Can set debug mode inside get or set
        get
        {
           return _name;
        }
        set
        {
           _name = value;
        }
   }

从技术上讲,我不认为有什么区别,因为财产只是围绕用户创建的或编译器自动创建的字段的包装器。财产的目的是加强封装,并提供轻量级的类方法功能。将字段声明为公共字段是一种不好的做法,但它没有任何问题。

其他信息:默认情况下,get和set访问器与属性本身一样可访问。通过对访问器应用更严格的访问修饰符,可以分别控制/限制访问器的可访问性(对于get和set)。

例子:

public string Name
{
    get
    {
        return name;
    }
    protected set
    {
        name = value;
    }
}

这里get仍然是公共访问的(因为属性是公共的),但set是受保护的(一个更受限制的访问说明符)。