有没有理由让房产没有吸气剂?

我的经理问我,使用带有二传手的房产是否是一个好习惯,但没有吸气剂。

public class PropertyWrapper { private MyClass _field; public MyClass Property { set { _field = value; } } public string FirstProperty { get { return _field.FirstProperty; } } public string SecondProperty { get { return _field.SecondProperty; } } } 

他将使用其他属性来显示私有字段中的属性,由此setter设置。

我的建议是只使用一个私有字段并在构造函数中设置它,在这种情况下可以正常工作。 如果我需要首先拥有一个构造对象(甚至可能使用多态),我仍然会更喜欢Load方法,而不是一个getter-less属性。

但我很感兴趣。 我们都非常关注最佳实践,并尝试确保我们的代码是标准化的。 有没有人有关于无吸气物业的官方文章? 或者更好 – 在.NET Framework本身中这种用法的一个例子?

官方文章: 开发类库的 设计指南 – > 成员设计指南 – > 属性设计

不提供仅设置属性。

如果无法提供属性getter,请使用方法来实现该function。 方法名称应以Set开头,后跟属性名称。 例如,AppDomain有一个名为SetCachePath的方法,而不是一个名为CachePath的只设置属性。

考虑到的问题是: 有没有人有任何关于无吸气剂属性的官方文章? 或者更好 – 在.NET Framework本身中这种用法的一个例子? 而不是意见; 我编写了一个快速测试应用程序来读取默认控制台应用程序中加载的所有类型的所有程序集的所有属性:

 foreach (var assem in AppDomain.CurrentDomain.GetAssemblies()) { foreach (var type in assem.GetTypes()) { foreach (var prop in type.GetProperties()) { if (!prop.CanRead) Console.WriteLine("Assembly: {0}; Type: {1}; Property: {2}", assem.FullName, type.Name, prop.Name); } } } 

结果是:

汇编:mscorlib,Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089; 类型:FileIOAccess; 属性:PathDiscovery

汇编:mscorlib,Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089; 类型:RedirectionProxy; 属性:ObjectMode

所以看起来框架很少使用它。 我建议做同样的事情。

编辑

有趣的是,在附加调试器的情况下运行相同的代码会产生更多结果:

 Assembly: mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: FileIOAccess; Property: PathDiscovery Assembly: mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: RedirectionProxy; Property: ObjectMode Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: AxHost; Property: Site Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: DataGridTextBoxColumn; Property: PropertyDescriptor Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: DisplayedBandsData; Property: FirstDisplayedFrozenCol Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: DisplayedBandsData; Property: FirstDisplayedFrozenRow Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: DisplayedBandsData; Property: LastDisplayedFrozenCol Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: DisplayedBandsData; Property: LastDisplayedFrozenRow Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: DisplayedBandsData; Property: LastDisplayedScrollingRow Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: ErrorProvider; Property: Site Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: WebBrowserBase; Property: Site Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: WebBrowser; Property: Site Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: DropDownButton; Property: UseComboBoxTheme Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: GridErrorDlg; Property: Details Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: GridErrorDlg; Property: Message Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: DropDownHolder; Property: ResizeUp Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: GridViewEdit; Property: DontFocus Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: GridViewEdit; Property: DisableMouseHook Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: MouseHook; Property: DisableMouseHook Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: ManifestSignedXml; Property: Resolver Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: ContainerProxy; Property: Bounds Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: RightToLeftProxy; Property: Bounds Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: TopDownProxy; Property: Bounds Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: BottomUpProxy; Property: Bounds Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: ElementProxy; Property: Bounds Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: VerticalElementProxy; Property: Bounds Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: IconComparer; Property: SortOrder Assembly: System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: MultiPropertyDescriptorGridEntry; Property: PropertyValue Assembly: System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: ConfigXmlDocument; Property: XmlResolver Assembly: System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: ConfigXmlDocument; Property: InnerText Assembly: System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: ProcessThread; Property: IdealProcessor Assembly: System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: ProcessThread; Property: ProcessorAffinity Assembly: System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: ConfigXmlAttribute; Property: InnerText Assembly: System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: ConfigXmlAttribute; Property: InnerXml Assembly: System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: AnonymousPipeServerStream; Property: ReadMode Assembly: System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: AnonymousPipeClientStream; Property: ReadMode Assembly: System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: ManifestSignedXml; Property: Resolver Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: XmlResolver; Property: Credentials Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: XmlNullResolver; Property: Credentials Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: XmlSecureResolver; Property: Credentials Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: XmlUrlResolver; Property: Credentials Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: XmlUrlResolver; Property: Proxy Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: XmlUrlResolver; Property: CachePolicy Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: XmlReaderSettings; Property: XmlResolver Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: XmlTextReader; Property: XmlResolver Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: XmlValidatingReader; Property: XmlResolver Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: DocumentXmlWriter; Property: NamespaceManager Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: DocumentXmlWriter; Property: Navigator Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: DocumentXmlWriter; Property: EndNode Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: XmlAttribute; Property: InnerText Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: XmlAttribute; Property: InnerXml Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: XmlDocument; Property: XmlResolver Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: XmlDocument; Property: InnerText Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: XmlUnspecifiedAttribute; Property: InnerText Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: XmlUnspecifiedAttribute; Property: InnerXml Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: XmlPreloadedResolver; Property: Credentials Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: XslTransform; Property: XmlResolver Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: XmlSchemaSet; Property: XmlResolver Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: XmlSchemaValidator; Property: XmlResolver Assembly: System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089; Type: XsdValidator; Property: Context 

我没有官方文章或例子……只有意见。

在我看来,一个无法读取的财产是一种愤怒和混淆的野兽。

归结为意图。 一个财产说“我打算让消费者读我,甚至可能写信给我”。 名为“SetSomeAttribute”的函数声明了一个只写意图。

还有整体,它的我的数据,所以为什么我不能只读它回来的东西。

因此,在我看来,使用只写属性是没有充分理由的。

拥有一个没有getter的属性是没有错的, 如果这是使你的代码最容易理解和可维护的东西 。 然而,这方面的好例子可能极为罕见。

我曾经使用过getter-less属性的最好的东西是unit testing类,其属性具有不可访问的setter。 例如:

 public class MyClass { public int MyId { get; protected set; } } public class MyClass_Test : MyClass { public int MyId_Set { set { MyId = value; } } } 

这样我就可以在unit testing中使用MyClass_Test ,并为MyId预设一个值,可以对特定方法进行unit testing。

此外,在直接回应您的示例时,使用private get可能是更好的方法:

 public class PropertyWrapper { public MyClass Property { private get; set; } public string FirstProperty { get { return Property.FirstProperty; } } public string SecondProperty { get { return Property.SecondProperty; } } } 

没什么可说的,你不能这样做,但看起来确实有点奇怪。 我会有一个私人财产和一个设置它的方法即

  private string _test; public void SetTest(string test) { _test = test; } 

你必须记住为什么存在属性。 它们取代了以下模式

 class Foo { private Bar _bar; public Bar GetBar() { return _bar; } public void SetBar(Bar bar) { _bar = bar; } } 

虽然拥有一个没有Setter的属性看起来很奇怪,但我认为没有Get方法的Set方法看起来很奇怪。

事实上,我很确定属性是语法糖,并被重写为get / set方法。 或者至少非常接近。

当由于某种原因,构造函数和方法注入都不适合您时,它们可能用于dependency injection。

但我无法想象这样的情况。

好吧,它们可以很好地用于对象初始化器中的私有字段:

 var obj = new MyClass { Prop1 = value1, Prop2 = value2 }; 

这可能是将它们作为构造函数参数编写的另一种方法:

 var obj = new MyClass(value1, value2); 

但是如果有许多(可选)参数,则writeonly属性可以很方便。

正如已经提出的那样,我认为答案是在问题的背景下最有意义的答案。 我可以想到只有一个setter only属性的两种选择,这可能值得尝试看看哪个是最有意义的:

  1. 定义一个接受单个参数的单独方法。
  2. 定义始终返回相同值的getter(例如null)。 这是否有意义或意外取决于背景。

您可以拥有更整洁的属性,并且可以在其上执行完全访问控制,而不会使用凌乱的_localVariable和属性语法。

例子 :

  ///  /// Publicly readable, privately settable. ///  public int FirstProperty { get; private set; } ///  /// Entirely private ///  private int SecondProperty { get; set; }