属性和字段之间的语义差异及其含义

Posted

技术标签:

【中文标题】属性和字段之间的语义差异及其含义【英文标题】:The semantic difference between a property and a field, and their implications 【发布时间】:2011-09-03 12:47:16 【问题描述】:

采用private string Property get; set;private string field

请注意,两者都是私有的(因此它们不会暴露在此类之外)并且该属性没有采用额外的验证。

关于语义,它们有不同的含义吗?从某种意义上说,它们在这样使用时可以互换吗?

当涉及到诸如(微?)性能之类的影响时,创建字段还是创建属性是否重要,即让编译器为您处理支持字段。

【问题讨论】:

非常相似:Using a private auto property instead of a simple variable for a programming standard 【参考方案1】:

当它们是私有的时,我知道的唯一区别是该属性不适合 outref 参数。

但大多数情况下,私有财产并没有带来任何优势(相对于一个领域),那何必呢? 可能存在(微)性能成本。我会更担心额外的混乱。

【讨论】:

【参考方案2】: 属性是关于字段的数据隐藏 私有财产没有多大意义,因为谁有权访问该财产,谁也可以访问该领域 自动属性与支持字段没有性能影响,因为编译器会吐出支持字段,但可能存在序列化/反序列化警告

更新

性能影响:

使用属性(自动或带有支持字段)与字段相比有轻微的性能,因为属性是一种方法并且需要调用 CLR virtcall

但正如我所说,使用属性并没有多大意义,我相信 字段更具可读性,因为通常可以立即通过 命名约定(以 下划线或驼峰式)。

【讨论】:

私有属性是否有意义,因为它们最有可能用于访问私有字段? 当您编译“发布”时,自动属性没有性能影响 -> 没有跟踪和优化。【参考方案3】:

您不能拥有对属性的引用,但可以获取对成员的引用。因此,如果您使用成员,您可能无法在以后出于任何原因将它们切换到属性,例如添加臭名昭著的验证。

【讨论】:

我在考虑这个问题,但由于这个原因,总是使用属性而不是私有成员,这样说是否明智? @Andreas Grech:我想这取决于。在某些情况下,成员足够明确,例如一些临时/助手/标志/任何值,在某些情况下我也会考虑属性。 如果最简洁的编码方式需要将ref 传递给成员(例如,可以将其提供给Interlocked 方法),则使用属性可能会强制使用更笨重的设计.如果由于某种原因最终无法避免使用属性,那么最好从使用笨重的设计开始,而不是使用干净的设计来实施系统,然后在现场使用笨拙的设计时将其替换为笨拙的设计。替换为属性。另一方面,如果成员永远不需要成为属性,则最好使用更简洁的设计。【参考方案4】:

我认为创建私有自动属性没有用。如果它不是自动的,它可以用作某种内部“事件处理程序”以使对象状态保持最新:每次字段更改时(通过设置器)在代码中的任何位置执行一些操作。

性能?我认为不会有问题,即使在微观层面上也不会。

【讨论】:

'我看不出有什么用'你确实是不正确的。看看我的帖子为什么。 @MajesticRa:我看到你还没有完全阅读我的答案。我发现 automatic 私有属性毫无用处,因为您无法向它们添加任何自定义逻辑。事实上,正如我在回答中提到的,我能找到的私有属性的唯一用途是集中你的类的一些状态逻辑,但是它们不能像 OP 所暗示的那样是自动的。【参考方案5】:

属性是函数。 字段是“至少具有类可见性的变量”。

所以如果你有私有财产和私有领域:


与性能点的区别:

如果您使用优化并且没有跟踪(属性被视为内联),则没有区别。

语义上的区别:

1) 形式上没有区别。 2) 更深入一点,有区别。由于属性是函数,因此您可以从 getter 和 setter 获得委托。并且可以将委托用作...委托,就像将此委托与其他委托一起放入列表中一样 (Create a delegate from a property getter or setter method)

与设计观点的区别:

但是属性是看起来像变量的函数。为什么需要看起来像变量的函数?

假设你有 Hand 类,而这只手有可变的指数。

 class Hand
 
     public int fingersNumber;
 

那你可能有很多类似的代码

 if(he is BadPerson) leftHand.fingersNumber--
 if(doctor.Heal()) leftHand.fingersNumber++

但在某些时候,您可能希望向 Hand 添加一些其他变量。可以说它是环数。而且您知道,每个手指的戒指不能超过 10 个。

 class Hand
 
     public int fingersNumber;
     public int ringsNumber;

 

现在,你不能只是这样做

 leftHand.fingersNumber-- 

因为你必须控制ringsNumber 对fingersNumber 的依赖。

因此,您必须创建一些检查这种依赖性的函数。此外,您必须对用户隐藏 FingerNumber 和 RingNumber,这样他们就无法在没有检查的情况下更改此字段。

 class Hand
 
     private int fingersNumber;
     private int ringsNumber; 
     public int GetFingersNumber()...check logic...
     public void SetFingersNumber(int value)...check logic...
     public int GetRingsNumber()...check logic...
     public void SetRingsNumber(int value)...check logic...
 

并将此函数用作

 if(he is BadPerson) leftHand.SetFingersNumber(leftHand.GetFingersNumber()-1)

这里的问题是旧代码 leftHand.fingersNumber-- 现在无法工作。而且从一开始你就不会知道将来会添加戒指。为了解决这些问题,将字段设置为私有并使用 Set 和 Get 函数来获取和更改变量已成为一种范例,并确保将来可以在其中添加任何逻辑并且代码可以正常工作!

Setters 和 Getters 是 C++、Java 和许多语言的现状。 但是 C# 的创建者更进一步,将这些 getter 和 setter 函数装饰为“属性”。

 class Hand
 
     private int fingersNumber; 
     public int FingersNumber
     
          getreturn fingersNumber;
          setfingersNumber=value;
     
     ...     
  
  ...
  if(he is BadPerson) leftHand.FingersNumber--;

但大多数时候人们创建这样简单的属性,你看这个例子,它是 5 行例程代码。因此,在某些版本的 C# 中添加了自动属性以简化程序员的生活。所以你的课可能看起来像

 class Hand
 
     public int FingersNumberget;set;
 

但您可以随时扩展此获取设置行为:

  class Hand
 
     private int fingersNumber; 
     public int FingersNumber
     
          get...check logic...
          set...check logic...
     

     ...     
  

而且它不会破坏任何代码。喜欢

  if(he is BadPerson) leftHand.FingersNumber--;

这就是属性,为什么使用它们以及与字段有什么区别。

正如我之前提到的,如果您使用优化,简单属性和自动属性具有与变量相同的性能。 Se反汇编或只是谷歌关于它。

【讨论】:

感谢您冗长的回答,但我的问题并不是关于一般的属性和字段。我在问使用私有属性与使用私有字段之间是否存在语义差异,我特别说该属性没有采用额外的验证。 形式上没有区别。如果您看到反汇编,如果您使用优化并无跟踪运行,则自动属性将被视为内联自动生成的字段。所以没有微观性能差异。 BUT 属性允许您在开发的进一步阶段添加验证或内存障碍。字段没有。那是专业。 我知道,我不是在争论你。在我问这个问题之前,我就知道你对房产的看法,而我的问题与此无关。那么,除了验证之外,私有字段和私有属性的主要区别是什么?

以上是关于属性和字段之间的语义差异及其含义的主要内容,如果未能解决你的问题,请参考以下文章

是否有适用于 C++ 的语义差异工具?

Python:pool.map 和 map 之间的语义差异?

NLP第十篇-语义分析

什么是值和引用语义及其区别

语义网的模型定义

二、词向量和语义