我刚刚意识到C# property construct 也可以与 private 访问修饰符一起使用:
private string Password { get; set; }
虽然这在技术上很有趣,但我无法想象何时使用它,因为 private field 甚至涉及 less ceremony :
private string _password;
我无法想象什么时候我需要能够在内部 get but not set 或 set but not get 私人领域:
private string Password { get; }
要么
private string Password { set; }
但是也许有一个 nested / inherited classes 的用例,或者可能是get / set可能包含 logic 而不是仅仅返回属性值的用例,尽管我倾向于保持属性严格简单并让显式方法做任何逻辑,例如 GetEncodedPassword()
.
Does anyone use private properties in C# for any reason or is it just one of those technically-possible-yet-rarely-used-in-actual-code constructs?
附录
很好的答案,阅读它们我剔除了私人 property 的这些用途:
当私人字段需要延迟加载时
-
当私有字段需要额外逻辑或计算值时
-
因为私有字段很难调试
-
以"present a contract to yourself"
-
在内部转换/简化公开属性作为序列化的一部分
-
包装要在类中使用的全局变量
14 回答
我时不时地使用它们 . 当你可以轻松地放入断点时,它们可以更容易地调试属性或您可以添加日志声明等 .
如果您以后需要以某种方式更改数据类型或者需要使用反射,也可以使用它 .
我使用私有属性来减少访问经常使用的子属性的代码 .
如果有许多子属性,它很有用 .
通常的做法是仅使用get / set方法修改成员,甚至是私有方法 . 现在,这背后的逻辑是让你知道你的get / set总是以特定的方式运行(例如,触发事件),这似乎没有意义,因为那些不会包含在属性方案中......但是旧习惯很难受 .
当存在与属性集或get相关的逻辑(想想延迟初始化)并且该属性在类中的一些地方使用时,它是完全有意义的 .
如果它只是一个直接的支持领域?没有什么可以成为一个很好的理由 .
如果我需要缓存一个值并想要延迟加载它,我会使用它们 .
正如其他人所提到的,我在代码中的主要用法是延迟初始化 .
私有属性优于字段的另一个原因是私有属性比私有字段更容易调试 . 我经常想知道这样的事情:“这个字段是意外设置的;谁是设置这个字段的第一个调用者?”如果你可以在setter上放一个断点然后点击它就会更容易 . 你可以把登录放在那里 . 您可以将性能指标放在那里 . 您可以放入在调试版本中运行的一致性检查 .
基本上,它归结为:代码远比数据强大 . 任何让我编写我需要的代码的技术都是很好的 . 字段不允许您在其中编写代码,属性可以 .
即使我不需要属性的getter或setter上的逻辑,我个人也会使用它 . 使用属性(即使是私有属性)确实可以帮助您在未来验证代码,以便以后可以根据需要将逻辑添加到getter中 .
如果我觉得某个属性最终可能需要额外的逻辑,我有时会将其包装到私有属性而不是使用字段,因此我不必在以后更改我的代码 .
在半相关案例中(虽然与您的问题不同),我经常在公共 property 上使用私人制定者:
这为您提供了一个公共getter,但保持setter私有 .
延迟初始化是一个可以整洁的地方,例如:
然后你可以写:
this.MyType
到处而不是this.mytype.Value
并封装它在一个地方懒惰地实例化的事实 .令人遗憾的是,C#不支持将支持字段作用于属性(即在属性定义中声明它)以完全隐藏它并确保只能通过属性访问它 .
私有get属性的一个好用法是计算值 . 有几次我有私有readonly的属性,只是对我的类型中的其他字段进行计算 . 它不值得一个方法,对其他类没有兴趣,所以它是私有 property .
我能想到的唯一一种用法
属性和字段不是一对一的 . 属性是关于类的接口(无论是关于它的公共接口还是内部接口),而字段是关于类的实现 . 不应将属性视为仅暴露字段的方式,它们应被视为暴露类的意图和目的的一种方式 .
就像您使用属性向您的消费者提供关于您的课程构成的 Contract 一样,您也可以出于非常类似的原因向您自己提交 Contract . 所以是的,我确实使用私有属性 . 有时,私有 property 可以隐藏实现细节,例如延迟加载,事实上属性实际上是多个字段和方面的集合,或者属性需要在每次调用时实际实例化(想想
DateTime.Now
) . 有时甚至在课堂后端对自己实施这一点也是有意义的 .我在序列化中使用它们,像
DataContractSerializer
或protobuf-net这样的东西支持这种用法(XmlSerializer
没有) . 如果您需要简化对象作为序列化的一部分,这将非常有用:我一直做的一件事是将"global"变量/缓存存储到
HttpContext.Current
好吧,正如没有人提到的那样,你可以使用它来验证数据或锁定变量 .
注意:锁定引用时,不会锁定对引用对象成员的访问 .
延迟引用:当延迟加载时,你可能最终需要执行异步,现在有AsyncLazy . 如果您使用的是旧版本而不是Visual Studio SDK 2015,或者不使用它,您也可以使用AsyncEx's AsyncLazy .