属性与公共成员变量[重复]
Posted
技术标签:
【中文标题】属性与公共成员变量[重复]【英文标题】:Properties vs Public member variables [duplicate] 【发布时间】:2012-08-06 03:30:02 【问题描述】:可能重复:What is the difference between a field and a property in C#
我是一名初级程序员,我已经阅读了所有关于类属性的内容。书籍指出属性允许您间接访问成员变量。好的,那么与仅公开该字段并直接访问它有什么不同呢?
这是 Jesse Liberty 的 Learning C# 3.0 中的一段话:
例如,您可能想要外部 类能够读取一个值,但不能改变它;或者你可能想写 一些代码,以便内部字段只能接受一定范围内的值。如果你 授予外部类免费访问您的成员字段的权限,您无法控制任何内容。
我不明白他在这里说什么。有人可以进一步解释这一点或举例说明我为什么要使用属性而不是公开该字段。据我所知,他们都会完成同样的事情......所以我显然在这里遗漏了一些东西。
【问题讨论】:
看看这个网站msdn.microsoft.com/en-us/library/79b3xss3%28v=vs.80%29.aspx 正确的链接是msdn.microsoft.com/en-us/library/79b3xss3.aspx。请不要发布特定版本的链接,除非您只希望该链接与特定版本相关。 【参考方案1】:到目前为止提供的其他答案提供了访问器/突变器逻辑优势的详细信息,但似乎都错过了关于对象封装的思想观点。
你看,类成员字段是一个实现细节。例如,如果您有一个表示集合的类,则可以将其实现为链表(并通过公共字段公开根节点),也可以将其实现为可调整大小的数组并公开 index0 成员。
揭示实现细节的问题在于,您会丢失类与其使用者之间的任何类型的已定义接口。通过确保通过定义的方法(由类本身控制)完成所有操作,您可以更轻松地使用并提供长期观点。例如,您可以更轻松地将集合实现从一种类型(链表)转换为另一种类型(数组),而不会违反与类的消费者的任何约定。
不必担心琐碎的访问器/修改器方法对性能的任何影响:JIT 编译器将内联属性方法。如果您运行一些基准测试,您会发现属性与字段的性能是相同的。
【讨论】:
这里的最佳答案。还值得一提的是,如果以后有必要从公开字段更改为属性,这也代表合同更改,并且需要重新编译所有依赖代码……如果您分发库,则尤其糟糕。 【参考方案2】:他是说属性可以提供 getter 但不能提供 setter,因此使它们成为只读(例如)
属性只是方法的语法糖,例如
public int SomeProperty get; set;
只是糖
private int _someProperty;
public int SomeProperty_get()
return _someProperty;
public void SomeProperty_set(int value)
_someProperty = value;
这意味着属性设置器/获取器可以应用纯公共字段不能应用的逻辑
编辑:我不完全确定 CLR 为自动属性提供支持字段的字段名称 - 这只是一个示例 :)
编辑2:
只读属性示例:
public int SomeProperty get;
最后是公共读取 - 私有写入(用于自动属性)
public int SomeProperty get; private set;
当您懒得在其中键入支持字段时非常有用:)
请记住,如果您可能希望将逻辑应用于成员,那么属性就是要走的路。这是许多框架的工作方式(例如,通过使用属性来跟踪“脏”对象以告诉某种对象管理器某些内容已更改,这使用公共字段是不可能的)
【讨论】:
【参考方案3】:属性可能有副作用,它们为“getter”和“setter”方法提供语法糖。
public class MyClass
int sizeValue = 0;
public int Size
get
return sizeValue;
set
if ( value < 10 ) throw new Exception("Size too small");
sizeValue = value;
属性也可以有不同级别的 get 和 set 保护,你不能用字段来做到这一点。
public class MyOtherClass
// only this object can set this.
public int Level
get; private set;
// only things in the same assembly can set this.
public string Name
get; internal set;
【讨论】:
我不同意贬义的“句法糖”。老实说,我相信“属性”远不止于此。恕我直言... 我不同意您将 "syntactic sugar" 视为贬义的解释。它被称为糖,因为它是可取的。 :) @paulsm4,这并不是一个否定的断言,除了很好地包装 get/set 方法逻辑之外,您还可以获得一种不同的反射类型,这可能会有所帮助。 你忽略了要点(封装,稳定的接口)。【参考方案4】:“属性”和“成员访问”之间存在许多重要区别。
最重要的是,您可以通过属性将成员设为只读(您可以访问状态,但不能更改它)。就像 Java 中的“getter()”和“setter()”方法。
您还可以从属性返回一个计算值(“即时”生成一个值,就像它是一个变量一样)。
【讨论】:
不保证新的答案,所以我会在这里添加它:另一个大人物能够向您的 setter 访问器添加数据验证。 我认为您可能会混淆术语:您可以将 property 设为只读。您不能将成员设为只读。 @Dan J - 我想说1)如果你的班级有一个成员,2)如果你想提供对该成员值的只读访问,那么 3)“属性”是一个很好的方法。我进一步提到,在 Java 中,由于缺少属性,提供“getter()”方法(没有相应的“setter()”)是完成相同事情的唯一方法。 @DanJ:当然可以;public readonly string Foo;
@Ed S:你是对的 ;)【参考方案5】:
属性可以这样配置:
它们是只读的,Public MyProp get;
它们是只写的Public MyProp set;
它们可以被外部对象读取,但只能由类的内部设置
公众号MyProp get; private set;
正如其他人所发布的,您也可以将逻辑放入您的 getter 和 setter。例如,在允许将属性设置为新值之前,您可以检查该值是否可以接受。
您不能对公共字段执行任何操作。
基本上,公共字段是您可以拥有的最愚蠢的一种属性。鉴于 .Net 现在允许为您的属性自动备份字段。没有充分的理由再使用公共字段了。
【讨论】:
自动实现的属性很好,但是当前编译器在您使用它们时不会生成有关字段滥用的警告(例如“字段从未使用过”或“字段从未分配给并将始终具有默认值 null")。当它们被忽视时,它会使捕捉这些错误变得稍微困难一些。不过我在精神上同意你的看法。【参考方案6】:如果你有Public Int MyAge
我可以将它设置为 -200 或 20,000,而你对此无能为力。
例如,如果您使用属性,则可以检查年龄是否在 0 到 150 之间。
编辑:根据 IanNorton 的示例(伙计,这很快)
【讨论】:
以上是关于属性与公共成员变量[重复]的主要内容,如果未能解决你的问题,请参考以下文章
start from the beginning-JAVA(成员变量与局部变量的区别封装构造方法)
JAVA_SE基础——26.[深入解析]局部变量与成员变量的区别