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


当前回答

当您希望您的私有变量(字段)可以被其他类中的类对象访问时,您需要为这些变量创建财产。

例如,如果我的变量名为“id”,而“name”是私有的但可能存在这样的情况,即类外部的读/写操作需要此变量。在这种情况下,属性可以帮助我根据为属性定义的get/set来读取/写入该变量。属性可以是readonly/writeonly/readwriteboth。

这是演示

class Employee
{
    // Private Fields for Employee
    private int id;
    private string name;

    //Property for id variable/field
    public int EmployeeId
    {
       get
       {
          return id;
       }
       set
       {
          id = value;
       }
    }

    //Property for name variable/field
    public string EmployeeName
    {
       get
       {
          return name;
       }
       set
       {
          name = value;
       }
   }
}

class MyMain
{
    public static void Main(string [] args)
    {
       Employee aEmployee = new Employee();
       aEmployee.EmployeeId = 101;
       aEmployee.EmployeeName = "Sundaran S";
    }
}

其他回答

在后台,属性被编译为方法。因此,Name属性被编译为get_Name()和set_Name(字符串值)。如果您研究编译的代码,您可以看到这一点。因此,在使用它们时会有(非常)小的性能开销。通常,如果向外部公开字段,则始终使用Property,如果需要验证值,则通常在内部使用Property。

差异-用途(何时和为什么)

字段是直接在类或结构中声明的变量。类或结构可以具有实例字段或静态字段,也可以同时具有两者。通常,应仅对具有专用或受保护的可访问性的变量使用字段。类向客户端代码公开的数据应该通过方法、财产和索引器提供。通过使用这些构造间接访问内部字段,可以防止输入值无效。

属性是提供读取、写入或计算私有字段值的灵活机制的成员。财产可以像公共数据成员一样使用,但它们实际上是称为访问器的特殊方法。这使得数据可以很容易地访问,并且仍然有助于提高方法的安全性和灵活性。财产使类能够公开获取和设置值的公共方式,同时隐藏实现或验证代码。get属性访问器用于返回属性值,set访问器用于分配新值。

基本区别和一般区别是:

领域

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

财产

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

我对一个字段的设计是,一个字段只需要由它的父级修改,也就是类修改。结果变量变为私有,然后为了能够赋予读取外部类/方法的权限,我只使用Get来遍历属性系统。然后,该字段由属性检索,并且是只读的!如果你想修改它,你必须通过方法(例如构造函数),我发现由于这种方法使你安全,我们可以更好地控制代码,因为我们“法兰”。我们可以很好地将所有的事情都公开,所以每个可能的情况,变量/方法/类等的概念。。。在我看来,这只是对代码开发和维护的一种帮助。例如,如果一个人使用公共字段恢复代码,那么他可以做任何事情,因此可以做与目标相关的“不合逻辑”的事情,即代码编写的逻辑。这是我的观点。

当我使用经典模型私有字段/公共只读财产时,对于10个私有字段,我应该编写10个公共财产!代码可以更快地变大。我发现了私有setter,现在我只对私有setter使用公共财产。setter在后台创建一个私有字段。

这就是为什么我以前的经典编程风格是:

public class MyClass
{
 private int _id;
 public int ID { get { return _id; } }
 public MyClass(int id)
 {
  _id = id;
 }
}

我的新编程风格:

public class MyClass
{
 public int ID { get; private set; }
 public MyClass(int id)
 {
  ID = id;
 }
}

由于他们中的许多人已经解释了财产和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;
        }
   }