属性和字段之间的语义差异及其含义
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】:当它们是私有的时,我知道的唯一区别是该属性不适合 out
和 ref
参数。
但大多数情况下,私有财产并没有带来任何优势(相对于一个领域),那何必呢? 可能存在(微)性能成本。我会更担心额外的混乱。
【讨论】:
【参考方案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 属性允许您在开发的进一步阶段添加验证或内存障碍。字段没有。那是专业。 我知道,我不是在争论你。在我问这个问题之前,我就知道你对房产的看法,而我的问题与此无关。那么,除了验证之外,私有字段和私有属性的主要区别是什么?以上是关于属性和字段之间的语义差异及其含义的主要内容,如果未能解决你的问题,请参考以下文章