在C#中,是什么使字段与属性不同?何时应该使用字段而不是属性?
当前回答
由于他们中的许多人已经解释了财产和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;
}
}
其他回答
在后台,属性被编译为方法。因此,Name属性被编译为get_Name()和set_Name(字符串值)。如果您研究编译的代码,您可以看到这一点。因此,在使用它们时会有(非常)小的性能开销。通常,如果向外部公开字段,则始终使用Property,如果需要验证值,则通常在内部使用Property。
差异-用途(何时和为什么)
字段是直接在类或结构中声明的变量。类或结构可以具有实例字段或静态字段,也可以同时具有两者。通常,应仅对具有专用或受保护的可访问性的变量使用字段。类向客户端代码公开的数据应该通过方法、财产和索引器提供。通过使用这些构造间接访问内部字段,可以防止输入值无效。
属性是提供读取、写入或计算私有字段值的灵活机制的成员。财产可以像公共数据成员一样使用,但它们实际上是称为访问器的特殊方法。这使得数据可以很容易地访问,并且仍然有助于提高方法的安全性和灵活性。财产使类能够公开获取和设置值的公共方式,同时隐藏实现或验证代码。get属性访问器用于返回属性值,set访问器用于分配新值。
财产是一种特殊的类成员。在财产中,我们使用预定义的Set或Get方法。它们使用访问器,通过访问器我们可以读取、写入或更改私有字段的值。
例如,让我们使用一个名为Employee的类,其中包含name、age和Employee_Id的私有字段。我们无法从类外部访问这些字段,但可以通过财产访问这些私有字段。
我们为什么使用财产?
公开类字段并公开它是有风险的,因为您无法控制分配和返回的内容。
为了通过示例清楚地理解这一点,让我们以一个具有ID、密码和姓名的学生班级为例。现在在这个例子中,公共领域的一些问题
ID不应为-ve。名称不能设置为空合格标记应为只读。如果缺少学生姓名,则不应返回姓名。
为了解决这个问题,我们使用Get和set方法。
// A simple example
public class student
{
public int ID;
public int passmark;
public string name;
}
public class Program
{
public static void Main(string[] args)
{
student s1 = new student();
s1.ID = -101; // here ID can't be -ve
s1.Name = null ; // here Name can't be null
}
}
现在我们以get和set方法为例
public class student
{
private int _ID;
private int _passmark;
private string_name ;
// for id property
public void SetID(int ID)
{
if(ID<=0)
{
throw new exception("student ID should be greater then 0");
}
this._ID = ID;
}
public int getID()
{
return_ID;
}
}
public class programme
{
public static void main()
{
student s1 = new student ();
s1.SetID(101);
}
// Like this we also can use for Name property
public void SetName(string Name)
{
if(string.IsNullOrEmpty(Name))
{
throw new exeception("name can not be null");
}
this._Name = Name;
}
public string GetName()
{
if( string.IsNullOrEmpty(This.Name))
{
return "No Name";
}
else
{
return this._name;
}
}
// Like this we also can use for Passmark property
public int Getpassmark()
{
return this._passmark;
}
}
来自维基百科——面向对象编程:
面向对象编程(OOP)是一种基于“对象”概念的编程范式,“对象”是以字段形式包含数据的数据结构,通常称为属性;和代码,以过程的形式,通常称为方法。(添加强调)
财产实际上是对象行为的一部分,但其设计是为了给对象的消费者提供使用对象数据的幻觉/抽象。
财产封装字段,从而使您能够对要设置或检索的值执行附加处理。如果您不需要对字段值进行任何预处理或后处理,那么使用财产通常是过分的。
推荐文章
- 实体框架核心:在上一个操作完成之前,在此上下文中开始的第二个操作
- 如何为构造函数定制Visual Studio的私有字段生成快捷方式?
- 如何使用JSON确保字符串是有效的JSON。网
- AppSettings从.config文件中获取值
- 通过HttpClient向REST API发布一个空体
- 如何创建类属性?
- 如何检查IEnumerable是否为空或空?
- 自动化invokerrequired代码模式
- 在c#代码中设置WPF文本框的背景颜色
- 在c#中,什么是单子?
- c#和Java中的泛型有什么不同?和模板在c++ ?
- c#线程安全快速(est)计数器
- 如何将此foreach代码转换为Parallel.ForEach?
- 如何分裂()一个分隔字符串到一个列表<字符串>
- 如何转换列表<字符串>列表<int>?