在C#中,是什么使字段不同于属性,以及何时应使用字段代替属性?


#1楼

(这实际上应该是评论,但我不能发表评论,因此,如果它不适合发表,请原谅)。

我曾经在一个推荐的实践是在公共属性而不是属性的地方工作,而等效的属性def只是在访问一个字段,例如:

get { return _afield; }
set { _afield = value; }

他们的理由是,如果需要,将来可以将公共场所转换为财产。 当时对我来说有点奇怪。 从这些帖子来看,似乎也没有多少人同意。 您可能会说些什么来尝试改变事情?

编辑:我应该补充一点,此位置的所有代码库都是在同一时间编译的,因此他们可能认为更改类的公共接口(通过将公共字段更改为属性)不是问题。


#2楼

使用属性,可以在更改属性值(也称为PropertyChangedEvent)时或在更改值以支持取消之前引发事件。

使用(直接访问)字段是不可能的。

public class Person {private string _name;public event EventHandler NameChanging;     public event EventHandler NameChanged;public string Name{get{return _name;}set{OnNameChanging();_name = value;OnNameChanged();}}private void OnNameChanging(){EventHandler localEvent = NameChanging;if (localEvent != null) {localEvent(this,EventArgs.Empty);}}private void OnNameChanged(){EventHandler localEvent = NameChanged;if (localEvent != null) {localEvent(this,EventArgs.Empty);}}
}

#3楼

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

字段是直接在类或结构中声明的变量。 一个类或结构可以具有实例字段或静态字段,或两者都有。 通常,应将字段用于具有私有或受保护的可访问性的变量 。 您的类公开给客户端代码的数据应通过方法,属性和索引器提供。 通过使用这些结构间接访问内部字段,可以防止输入值无效。

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


#4楼

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


#5楼

IMO,Properties只是我们之前使用的“ SetXXX()”“ GetXXX()”函数/方法/接口对,但它们更加简洁优雅。


#6楼

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

例如,如果我有一个名为“ id”和“ name”的变量,它们是私有的,但可能存在该变量在类外进行读/写操作所需的情况。 在这种情况下,property可以帮助我根据为该属性定义的get / set来获取要读取/写入的变量。 一个属性可以是readonly / writeonly / readwrite两者。

这是演示

class Employee
{// Private Fields for Employeeprivate int id;private string name;//Property for id variable/fieldpublic int EmployeeId{get{return id;}set{id = value;}}//Property for name variable/fieldpublic 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";}
}

#7楼

由于其中许多人已经解释了PropertiesField技术利弊,因此现在该开始研究实时示例了。

1.属性允许您设置只读访问级别

考虑dataTable.Rows.CountdataTable.Columns[i].Caption 。 它们来自DataTable类,并且都对我们公开。 它们的访问级别的不同之处在于,我们无法将value设置为dataTable.Rows.Count但可以读写dataTable.Columns[i].Caption 。 通过Field可以做到吗? 没有!!! 这只能通过Properties来完成。

public class DataTable
{public class Rows{       private string _count;        // This Count will be accessable to us but have used only "get" ie, readonlypublic int Count{get{return _count;}       }} public class Columns{private string _caption;        // Used both "get" and "set" ie, readable and writablepublic string Caption{get{return _caption;}set{_caption = value;}}       }
}

2. PropertyGrid中的属性

您可能已经在Visual Studio中使用Button 。 它的属性显示在PropertyGrid例如TextName等。当我们拖放按钮时,当我们单击属性时,它将自动找到Button类并过滤Properties并在PropertyGrid显示该PropertyGrid (其中不会显示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 ,将显示属性NameText ,但不显示SomeProperty 。 为什么??? 因为Properties可以接受Attributes 。 如果[Browsable(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 _countreturn _count;}
}

4.在绑定源中只能使用属性

绑定源可以帮助我们减少代码行数。 BindingSource不接受Fields 。 我们应该为此使用Properties

5.调试模式

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

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

#8楼

传统上,私有字段是通过getter和setter方法设置的。 为了减少代码,您可以使用属性来设置字段。


#9楼

当您有一个“汽车”课程时。 属性是颜色,形状。

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


#10楼

属性公开字段。 字段(几乎总是)应该对类保持私有,并可以通过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 fieldpublic 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 youpublic int AnotherProperty{get;set;}
}

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

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


#11楼

面向对象的编程原理说,一个类的内部工作应该对外界隐藏。 如果公开一个字段,则本质上就是公开该类的内部实现。 因此,我们使用属性(或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
}

#12楼

如果要使用线程原语,则必须使用字段。 属性会破坏您的线程代码。 除此之外,科里所说的是正确的。


#13楼

属性封装字段,从而使您可以对要设置或检索的值执行其他处理。 如果您将不对字段值进行任何预处理或后处理,则使用属性通常是过高的。


#14楼

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

如果编写用于广泛使用的类库(例如数百万人使用的.NET Framework),则可能会出现问题。 但是,如果您要在一个小的代码库(例如<= 5万行)内编写一个内部使用的类,那实际上就没什么大不了的,因为没有人会受到您的更改的不利影响。 在那种情况下,这实际上取决于个人喜好。


#15楼

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

因此,可以说您只想将一个值设置为整数字段(如果该值大于x),否则抛出异常。

真正有用的功能。


#16楼

在后台将属性编译为方法。 因此,将Name属性编译为get_Name()set_Name(string value) 。 如果您研究编译的代码,则可以看到此信息。 因此,使用它们时(非常)很小的性能开销。 通常,如果将字段暴露在外部,则将始终使用属性;如果需要验证值,则经常在内部使用它。


#17楼

属性支持非对称访问,即,您可以具有getter和setter或仅是两者之一。 类似地,属性支持对getter / setter的个别可访问性。 字段始终是对称的,即,您始终可以同时获取和设置值。 唯一的例外是只读字段,在初始化后显然无法设置该字段。

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

字段可以用于out / ref参数,而属性可以不使用。 属性支持其他逻辑–可以用于实现延迟加载等。

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

在大多数情况下都使用属性,但要避免产生副作用。


#18楼

一个重要的区别是接口可以具有属性,但不能具有字段。 对我而言,这强调了应使用属性来定义类的公共接口,而字段则应在类的私有内部工作中使用。 通常,我很少创建公共字段,并且类似地,我很少创建非公共属性。


#19楼

我将为您提供一些使用属性的示例,这些属性可能会导致齿轮旋转:

  • 延迟初始化 :如果您拥有一个对象的属性,该属性的加载成本很高,但是在正常的代码运行中却没有得到太多访问,则可以通过该属性延迟其加载。 这样,它就坐在那里,但是当另一个模块第一次尝试调用该属性时,它会检查基础字段是否为空-如果是,它将继续进行加载并将其加载,而调用模块则未知。 这样可以大大加快对象的初始化速度。
  • 脏跟踪:我实际上是从我在StackOverflow上自己的问题中学到的。 当我有很多对象的值在运行中可能已更改时,我可以使用该属性来跟踪是否需要将它们保存回数据库。 如果对象的单个属性没有更改,则IsDirty标志不会被触发,因此,在确定需要返回数据库的内容时,保存功能将跳过该标志。

#20楼

MSDN上的这个页面有一个比较和提示,在以下情况下使用哪一个:

https://msdn.microsoft.com/en-us/library/9d65as2e(v=vs.90).aspx


#21楼

字段是普通成员变量或类的成员实例。 属性是获取和设置其值抽象 。 属性也称为访问器,因为如果您将类中的字段公开为私有,则它们提供了一种更改和检索字段的方法。 通常,应将成员变量声明为私有,然后为其声明或定义属性。

  class SomeClass{int numbera; //Field//Property public static int numbera { get; set;}}

#22楼

这里的第二个问题,“当应在现场使用,而不是财产?”,仅在简要介绍了这对方的回答还挺这一个了 ,但没有真正的细节。

总的来说,所有其他答案都是关于良好设计的问题:相对于暴露字段,更喜欢暴露属性。 虽然你可能不会经常发现自己说“哇,想象有多少糟糕的事情是,如果我做了,而不是财产这个领域”,这是这么多难得想到的情况下,你会说:“哇,感谢上帝,我在这里使用的是田地,而不是财产。”

但是,字段具有优于属性的一个优点,那就是它们可以用作“ ref” /“ out”参数。 假设您有一个具有以下签名的方法:

public void TransformPoint(ref double x, ref double y);

并假设您想使用该方法来转换这样创建的数组:

System.Windows.Point[] points = new Point[1000000];
Initialize(points);

我认为这是最快的方法,因为X和Y是属性:

for (int i = 0; i < points.Length; i++)
{double x = points[i].X;double y = points[i].Y;TransformPoint(ref x, ref y);points[i].X = x;points[i].Y = y;
}

那将是相当不错的! 除非您有其他证明的测量方法,否则没有理由发臭。 但我相信,从技术上讲,它并不能保证达到以下速度:

internal struct MyPoint
{internal double X;internal double Y;
}// ...MyPoint[] points = new MyPoint[1000000];
Initialize(points);// ...for (int i = 0; i < points.Length; i++)
{TransformPoint(ref points[i].X, ref points[i].Y);
}

自己进行一些测量 ,带有字段的版本大约要花费带有属性的版本(.NET 4.6,Windows 7,x64,发布模式,未连接调试器)的61%的时间。 TransformPoint方法获得的成本越高,差异变得越不明显。 要自己重复一遍,请先注释掉第一行,然后注释掉第一行。

即使上面没有任何性能上的好处,在其他地方也可以使用ref和out参数可能是有益的,例如在调用Interlocked或Volatile系列方法时。 注意:如果这是您的新手,那么Volatile基本上是一种实现volatile关键字提供的相同行为的方法。 因此,就像volatile一样,它不能神奇地解决所有线程安全问题,就像它的名字暗示的那样。

我绝对不希望我提倡您去“哦,我应该开始显示字段而不是属性”。 关键是,如果您需要在带有“ ref”或“ out”参数的调用中定期使用这些成员,尤其是在那些可能是简单值类型,不太可能不需要任何属性的增值元素的调用上,可以争论。


#23楼

来自Wikipedia- 面向对象的编程

面向对象编程(OOP)是一种基于“对象”概念的编程范式,“对象”是包含数据的数据结构, 采用字段的形式 ,通常称为属性; 以及以程序形式的代码,通常称为方法(强调)

属性实际上是对象行为的一部分,但旨在使对象的使用者获得使用对象数据的幻觉/抽象。


#24楼

属性是一种特殊的类成员,在属性中我们使用预定义的Set或Get方法,它们使用访问器来读取,写入或更改私有字段的值。

例如,让我们以名为Employee的类为例,该类具有用于名称,年龄和Employee_Id的私有字段。 我们不能从类外部访问这些字段,但是可以通过属性访问这些私有字段。

为什么使用属性?

将类公开并公开是有风险的,因为您将无法控制分配和返回的内容。

为了通过一个例子清楚地理解这一点,让我们参加一个具有ID,密码,姓名的学生班。 现在在此示例中,公共领域存在一些问题

  • ID不应该是-ve。
  • 名称不能设置为空
  • 通过标记应为只读。
  • 如果缺少学生姓名,则应返回“无姓名”。

要解决此问题,我们使用Get and 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 -ves1.Name = null ; // here Name can't be null}
}

现在我们以get和set方法为例

public class student
{private int _ID;private int _passmark;private string_name ;// for id propertypublic 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 propertypublic 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 propertypublic int Getpassmark(){return this._passmark;}
}

#25楼

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

当我使用经典模型私有字段/公共只读属性时,对于10个私有字段,我应该编写10个公共属性! 代码可以更快地完成。 我发现了私人二传手,现在我只将公共财产与私人二传手一起使用。 设置员在后台创建一个私有字段。

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

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

#26楼

附加信息:默认情况下,get和set访问器与属性本身一样可访问。 您可以通过对它们应用更严格的访问修饰符来单独控制/限制访问者可访问性(对于get和set)。

例:

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

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


#27楼

属性用于公开字段。 他们使用访问器(设置,获取),通过它们可以读取,写入或操作私有字段的值。

属性未命名存储位置。 相反,它们具有读取,写入或计算其值的访问器。

使用属性,我们可以对在字段上设置的数据类型设置验证。

例如,我们有一个私有整数字段age,因为age不能为负,所以我们应该允许正值。

我们可以使用getter和setter以及使用property以两种方式实现此目的。

 Using Getter and Setter// fieldprivate int _age;// setterpublic void set(int age){if (age <=0)throw new Exception();this._age = age;}// getterpublic int get (){return this._age;}Now using property we can do the same thing. In the value is a key wordprivate int _age;public int Age{get{return this._age;}set{if (value <= 0)throw new Exception()}}

自动实现的属性,如果我们在获取和设置访问器中不加逻辑,则可以使用自动实现的属性。

当您使用自动实现的属性编译时,将创建一个私有的匿名字段 ,该字段只能通过get和set访问器进行访问。

public int Age{get;set;}

抽象属性抽象类可能具有抽象属性,应在派生类中实现

public abstract class Person{public abstract string Name{get;set;}public abstract int Age{get;set;}}// overriden something like this
// Declare a Name property of type string:public override string Name{get{return name;}set{name = value;}}

我们可以私下设置属性,在此我们可以私下设置auto属性(在类中设置with)

public int MyProperty
{get; private set;
}

您可以使用此代码实现相同的目的。 此属性集功能不可用,因为我们必须直接将值设置为字段。

private int myProperty;
public int MyProperty
{get { return myProperty; }
}

#28楼

考虑一下:您有一个房间,有一扇门可以进入这个房间。 如果要检查谁进入房间并保护房间安全,则应使用属性,否则它们将无门可乘,每个人都容易进入而无任何法规

class Room {public string sectionOne;public string sectionTwo;
}Room r = new Room();
r.sectionOne = "enter";

人们可以很容易地进入第一个部分,没有任何检查

class Room
{private string sectionOne;private string sectionTwo;public string SectionOne {get {return sectionOne; }set { sectionOne = Check(value); }}
}Room r = new Room();
r.SectionOne = "enter";

现在,您检查了此人,并知道他是否有恶魔


#29楼

在大多数情况下,它将是您访问的属性名,而不是变量名( 字段 ),其原因是,在.NET和C#中,这被认为是一种很好的做法,尤其是保护类中的所有数据,无论是实例变量还是静态变量(类变量),因为它都与类相关联。

使用相应的属性保护所有这些变量,这些属性使您可以定义, 设置和获取 访问器 ,并在处理这些数据时进行验证等操作。

但是在其他情况下,例如Math类 (系统名称空间),该类中内置了几个静态属性。 其中之一是数学常数PI

例如。 数学PI

而且由于PI是一条定义明确的数据,因此我们不需要具有多个PI副本,因此它始终是相同的值。 因此,有时会使用静态变量在类的对象之间共享数据,但是当变量只需要一个数据副本时,它们也常用于常量信息。


#30楼

字段是类中的变量。 字段是您可以通过使用访问修饰符封装的数据。

属性与字段类似,因为它们定义状态和与对象关联的数据。

与字段不同,属性具有一种特殊的语法,该语法控制一个人如何读取数据和写入数据,这些称为get和set运算符。 设置逻辑通常可用于进行验证。


#31楼

基本区别和一般区别是:

领域

  • 始终授予获取和设置访问权限
  • 不会引起副作用(抛出异常,调用方法,更改字段(除已设置的字段外)等)

性质

  • 并非总是同时获得获取和设置访问权限
  • 引起副作用

#32楼

尽管字段和属性看起来彼此相似,但是它们是2种完全不同的语言元素。

  1. 字段是如何在类级别存储数据的唯一机制。 字段在概念上是类范围内的变量。 如果要将一些数据存储到类(对象)的实例中,则需要使用字段。 别无选择。 尽管属性无法存储任何数据,但看起来它们可以存储数据。 见下面。

  2. 另一方面,属性从不存储数据。 它们只是一对方法(获取和设置),可以用与字段类似的方式在语法上调用它们,并且在大多数情况下,它们访问(用于读取或写入)字段,这是造成混淆的原因。 但是由于属性方法是常规C#方法(有一些限制,例如固定原型),所以常规方法可以执行常规方法。 这意味着它们可以具有1000行代码,可以引发异常,调用其他方法,甚至可以是虚拟的,抽象的或覆盖的。 使属性与众不同的原因是C#编译器将一些额外的元数据存储到程序集中,可用于搜索特定属性-广泛使用的功能。

获取和设置属性方法具有以下原型。

PROPERTY_TYPE get();void set(PROPERTY_TYPE value);

因此,这意味着可以通过定义一个字段和2种相应方法来“模拟”属性。

class PropertyEmulation
{private string MSomeValue;public string GetSomeValue(){return(MSomeValue);}public void SetSomeValue(string value){MSomeValue=value;}
}

对于不支持属性的编程语言(例如标准C ++),这种属性仿真是典型的。 在C#中,您应该始终首选属性作为访问字段的方式。

因为只有字段可以存储数据,所以这意味着更多的字段类别包含,此类类别将消耗更多的内存对象。 另一方面,在类中添加新属性不会使此类对象更大。 这是例子。

class OneHundredFields
{public int Field1;public int Field2;...public int Field100;
}OneHundredFields Instance=new OneHundredFields() // Variable 'Instance' consumes 100*sizeof(int) bytes of memory.class OneHundredProperties
{public int Property1{get{return(1000);}set{// Empty.}}public int Property2{get{return(1000);}set{// Empty.}}...public int Property100{get{return(1000);}set{// Empty.}}
}OneHundredProperties Instance=new OneHundredProperties() // !!!!! Variable 'Instance' consumes 0 bytes of memory. (In fact a some bytes are consumed becasue every object contais some auxiliarity data, but size doesn't depend on number of properties).

尽管属性方法可以做任何事情,但在大多数情况下,它们用作访问对象字段的一种方式。 如果要使其他类可以访问该字段,则可以通过两种方法进行。

  1. 将字段设为公开-不建议这样做。
  2. 使用属性。

这是一个使用公共字段的类。

class Name
{public string FullName;public int YearOfBirth;public int Age;
}Name name=new Name();name.FullName="Tim Anderson";
name.YearOfBirth=1979;
name.Age=40;

虽然代码是完全有效的,但从设计的角度来看,它有几个缺点。 由于字段可以读写,因此不能阻止用户写入字段。 您可以应用readonly关键字,但是通过这种方式,您必须仅在构造函数中初始化readonly字段。 而且,没有什么可以阻止您将无效值存储到字段中。

name.FullName=null;
name.YearOfBirth=2200;
name.Age=-140;

该代码有效,尽管所有分配都是不合逻辑的,但仍将执行。 Age具有负值, YearOfBirth将来并且与Age不对应,并且FullName为null。 使用字段,您不能阻止class Name用户犯此类错误。

这是带有可解决这些问题的属性的代码。

class Name
{private string MFullName="";private int MYearOfBirth;public string FullName{get{return(MFullName);}set{if (value==null){throw(new InvalidOperationException("Error !"));}MFullName=value;}}public int YearOfBirth{get{return(MYearOfBirth);}set{if (MYearOfBirth<1900 || MYearOfBirth>DateTime.Now.Year){throw(new InvalidOperationException("Error !"));}MYearOfBirth=value;}}public int Age{get{return(DateTime.Now.Year-MYearOfBirth);}}public string FullNameInUppercase{get{return(MFullName.ToUpper());}}
}

类的更新版本具有以下优点。

  1. 检查FullNameYearOfBirth的无效值。
  2. Age不可写。 从YearOfBirth和当前年份开始YearOfBirth
  3. 一个新的属性FullNameInUppercase转换FullName大写。 这是属性用法的一些人为设计示例,其中属性通常用于以更适合用户的格式显示字段值-例如,使用特定于DateTime格式的数字的当前语言环境。

除此之外,可以将属性定义为虚拟的或覆盖的-仅因为它们是常规的.NET方法。 相同的规则适用于此类属性方法和常规方法。

C#还支持索引器,这些索引器是在属性方法中具有索引参数的属性。 这是例子。

class MyList
{private string[]                 MBuffer;public MyList(){MBuffer=new string[100];}public string this[int Index]{get{return(MBuffer[Index]);}set{MBuffer[Index]=value;}}
}MyList   List=new MyList();List[10]="ABC";
Console.WriteLine(List[10]);

由于C#3.0允许您定义自动属性。 这是例子。

class AutoProps
{public int Value1{get;set;}public int Value2{get;set;}
}

即使class AutoProps包含属性(或看起来像),它也可以存储2个值,并且此类的对象的大小等于sizeof(Value1)+sizeof(Value2) = 4 + 4 = 8个字节。

这样做的原因是简单的。 定义自动属性时,C#编译器会生成自动代码,其中包含隐藏字段和带有属性方法的属性,该属性方法可访问此隐藏字段。 这是编译器生成的代码。

这是ILSpy从编译的程序集生成的代码。 类包含生成的隐藏字段和属性。

internal class AutoProps
{[CompilerGenerated][DebuggerBrowsable(DebuggerBrowsableState.Never)]private int <Value1>k__BackingField;[CompilerGenerated][DebuggerBrowsable(DebuggerBrowsableState.Never)]private int <Value2>k__BackingField;public int Value1{[CompilerGenerated]get{return <Value1>k__BackingField;}[CompilerGenerated]set{<Value1>k__BackingField = value;}}public int Value2{[CompilerGenerated]get{return <Value2>k__BackingField;}[CompilerGenerated]set{<Value2>k__BackingField = value;}}
}

因此,如您所见,编译器仍然使用字段来存储值-因为字段是将值存储到对象中的唯一方法。

如您所见,尽管属性和字段具有相似的用法语法,但它们是非常不同的概念。 即使您使用自动属性或事件,隐藏字段也是由编译器生成的,用于存储实际数据。

如果您需要使外部用户(您的类的用户)可以访问字段值,请不要使用公共字段或受保护的字段。 字段始终应标记为私有。 属性使您可以进行值检查,格式设置,转换等,并且通常可以使您的代码更安全,更易读且可扩展,以备将来修改之用。

字段和属性之间有什么区别?相关推荐

  1. java中属性是什么意思啊_Java中的字段和属性到底有什么区别?

    Java中的字段和属性到底是什么?他们的含义真的是相同的吗?如果不同,那他们到底又分别是何含义呢? 相信上面的问题,对于很多Java初学者都是相当困惑的,但是好像把他们理解为一个含义也没啥问题,很多J ...

  2. CSS定位布局display/float/position属性之间的关系/区别和如何使用取值行为机制

    float: left|right; 可以自动排列自动折行, 但需要clear来配合清除浮动; display: inline-block; 有些时候可以替代float实现相同的效果. positio ...

  3. 在WPF中,x:Name和Name属性之间有什么区别?

    标题说明了一切. 有时似乎Name和x:Name属性是可互换的. 那么,它们之间的明确区别是什么?何时使用一种优于另一种呢? 以错误的方式使用它们是否会对性能或内存产生影响? #1楼 它们不是同一件事 ...

  4. 字段与属性 c# 1613532992

    字段与属性 c# 1613532992 明确公有字段,私有字段,属性的用法与区别

  5. UIView 的 alpha、hidden 和 opaque 属性之间的关系和区别

                     UIView 的 alpha.hidden 和 opaque 属性之间的关系和区别 UIView的这几个属性让我困惑了好一阵子,通过翻看官方文档和stackoverf ...

  6. C#中的字段与属性的区别及属性的作用

    C#中的字段与属性的区别及属性的作用 先上代码 public class Employee {//字段private string name;//属性public string Name {get { ...

  7. ng-model和ng-bind之间有什么区别

    本文翻译自:What's the difference between ng-model and ng-bind I'm currently learning AngularJS and am hav ...

  8. C# swich, constant, readonly,static, StringBuilder 和字段与属性

    switch语句 switch语句中各个常量表达式的值不能相等. 此外, C#还规定每个case分支都必须以break.return.goto或throw语句来结束, 而且语句中的任何代码都不能修改控 ...

  9. 基于C#的GIS开发20210422之C#知识点总结、数组、数据类型、字符串总结、函数重载、字段与属性的区分、构造函数的应用、属性设置、普通类与抽象类、面向对象关系梳理

    在20210419的基础上进行改进,和学习. 20210422笔记 ①C#小知识点总结 一.C#中的数组定义 0)数组声明 1)一维数组: 2)二维数组 3)数组初始化 4)数组的访问 C# 中 fo ...

最新文章

  1. 关于WPS页面横向问题
  2. 配置Eureka高可用
  3. 论文浅尝 - IJCAI | Knowledge is NOT always you need: 外部知识注入预训练模型的利与弊...
  4. 我在暴躁同事小张的胁迫下学会了Go的交叉编译和条件编译
  5. ACM学习历程—HDU1584 蜘蛛牌(动态规划 状态压缩 || 区间DP)
  6. Linux文件中批量转换时间戳,linux 文件日期转时间戳
  7. PHP laravel系列之迷你博客搭建
  8. OkHttp简单封装
  9. 有关苹果手机下载应用后提示不受信任的企业开发者解决方案:
  10. 「Adobe国际认证」Adobe Photoshop,如何裁剪并拉直照片?
  11. 关于项目编译工具ninja、make、cmake的区别与优劣
  12. SpringBoot整合Prometheus实现业务指标上报
  13. selenium处理iframe标签
  14. 微信小程token_微信小程序url与token如何设置
  15. 我对计算机的看法英语作文,我对网络的看法 My Concepts on Internet 英语作文范文...
  16. The request was rejected because the URL contained a potentially malicious String “//“ 报错
  17. MySQL空间函数——ST_AsText走过的坑
  18. 如何获取百度云下载直链
  19. 计算机垃圾回收站桌面上找不到,桌面上的回收站不见了怎么办?桌面上的回收站不见了解决方法...
  20. 常用的Linux命令(面试/工作必备)

热门文章

  1. 算法---------宝石与石头
  2. 我教你怎么玩转git
  3. mongodb数据合并设计_MongoDB:如何将来自多个集合的数据合并成一个.?
  4. Android自定义RulerView
  5. Swift 反射Mirror的使用
  6. Flutter开发之HTTP网络请求:HttpClient(26)
  7. postman test 脚本
  8. Matplotlib中中文不显示问题
  9. scanf函数详解与缓冲区
  10. windowsnbsp;下搭建apachenbsp;phpnbsp;mysqlnbsp;p…