10

Today at work one of my colleague reviewed my code, and suggested that I remove a set-only property and use a method instead.

As we both were busy with other things, he told me to look at the Property Design section from "Framework Design Guidelines" book. In the book the writer just said to avoid:

Properties with the setter having broader accessibility than the getter

And now I'm wondering why it is not recommended to have set-only property? Can someone clarify for me?

2
  • 6
    Can you describe the situation where you thought a set-only property was appropriate? It might make the answers a little more relevant.
    – JohnFx
    Feb 22 '11 at 16:41
  • 1
    I'm trying to think of an example that makes sense semantically. The only thing that comes to mind is a Password property on a User class. You can set it, but you can't get it. You could then have a readonly HashedPassword property. Calling the set would do the hash and change the HashedPassword property. I wouldn't yell at you if you did that. Feb 22 '11 at 17:04
16

I think it may have to do with expectations. Set-only properties are uncommon and properties are typically used for "dumb" sets just to store a value without much processing. If you're doing a lot of work in a setter, it is better to use a method -- people expect methods to potentially take a long time to execute and to potentially have side-effects. Implementing similar kind of behaviour in a property may result in code that violates expectations.

Here's a relevant section of Microsoft's Property Usage Guidelines:

Properties vs. Methods

Class library designers often must decide between implementing a class member as a property or a method. In general, methods represent actions and properties represent data. Use the following guidelines to help you choose between these options.

  • Use a property when the member is a logical data member. In the following member declarations, Name is a property because it is a logical member of the class.
public string Name
{
    get 
    {
        return name;
    }
    set 
    {
        name = value;
    }
}

Use a method when:

  • The operation is a conversion, such as Object.ToString.
  • The operation is expensive enough that you want to communicate to the user that they should consider caching the result.
  • Obtaining a property value using the get accessor would have an observable side effect.
  • Calling the member twice in succession produces different results.
  • The order of execution is important. Note that a type's properties should be able to be set and retrieved in any order.
  • The member is static but returns a value that can be changed.
  • The member returns an array. Properties that return arrays can be very misleading. Usually it is necessary to return a copy of the internal array so that the user cannot change internal state. This, coupled with the fact that a user can easily assume it is an indexed property, leads to inefficient code. In the following code example, each call to the Methods property creates a copy of the array. As a result, 2^n+1 copies of the array will be created in the following loop.
Type type = // Get a type.
for (int i = 0; i < type.Methods.Length; i++)
{
   if (type.Methods[i].Name.Equals ("text"))
   {
      // Perform some operation.
   }
}

[...skipped longer example...]

Read-Only and Write-Only Properties

You should use a read-only property when the user cannot change the property's logical data member. Do not use write-only properties.

1
  • Yes - the principle of least surprise operates here. Feb 22 '11 at 16:49
6

Because it simply makes no sense in most cases. What property might you have which you can set but not read?

If OO is meant to better represent the real world, a set only property is likely to suggest that your modelling is pretty off.

Edit: See also: https://stackoverflow.com/questions/4564928/are-set-only-properties-bad-practice which essentially says it's unintuitive and a set only property is basically a method by another name so you should use a method.

3
  • 2
    I've used set-only properties before. They write to a private field of the object to configure it's behavior. They're useful when external code doesn't need to know the current value, but might need to change it. That's rare, of course, but I've seen it happen. Feb 22 '11 at 16:48
  • @Mason - I certainly wouldn't ever go as far as saying you should never use them but they should essentially be the exception rather than the rule. Feb 22 '11 at 16:56
  • @MasonWheeler isn't that approximately Foo Foo { private get; set; }? I wouldn't call that write only
    – Caleth
    Jan 16 '20 at 13:46
6

Well, I imagine that if you can set a property on something but never get it, you'll never know if something else changes/overwrites the value that you set. That could be a problem if you rely on the value that you set, and you are unable (for some reason) to persist it until the time that you'd want to get it.

Using a method instead of a set-only property will be slightly less confusing for a user. The name of the method usually indicates set- or get-, but property names don't normally indicate that something can only be set and not be gotten. I suppose if the property were something like "ReadOnlyBackgroundColour" it would not be confusing to other coders, but that would just look weird.

8
  • I agree, but how would a setter method be any different in this case? Feb 22 '11 at 16:41
  • 1
    @Travis Christian: It sounds like OP is working with a situation where there is a setter but no getter. So they can set something, but they'll never know if it changes later. Feb 22 '11 at 16:43
  • @Frustrated But they'd also never know if something was changed again with a method either.
    – Adam Lear
    Feb 22 '11 at 16:47
  • @Anna Lear♦: If there's a getter, you can at least test the value before using it if you have a point in your code where the value you had set may be suddenly in doubt. Feb 22 '11 at 16:51
  • 3
    @Frustrated I agree. It's just that the question was about using a set-only property vs using a method to do the same thing.
    – Adam Lear
    Feb 22 '11 at 17:01
-1

This is a very old topic but one that has jumped into my view at this late stage and I'd like some comments as I try to make a case for write-only properties...

I have a set of ActiveReport classes that are part of a website that are instantiated and run on postback after a number of user selections.

The VB code looks something like this:

  Public Class SomeReport
    Private greader As New GenericReporting.CommonReader("AStoredProcedure", 
                                      {New SqlParameter("budget_id", 0)})

    Public WriteOnly Property BudgetID As Integer
      Set(value As Integer)
        greader.Parameters("budget_id").Value = value
      End Set
    End Property

    Public Sub New(Optional budget_id As Integer = 0)
      ' This call is required by the designer.
      InitializeComponent()

      ' Add any initialization after the InitializeComponent() call.
      BudgetID = budget_id
    End Sub
  End Class

These reports use generic guts, CommonReader takes a stored procedure and an array of default SqlParameters, each of which has an associated WriteOnly property that, depending on the report design, could be passed in as a parameter on instantiation or set by the user after instantiation before calling the reports Run method.

  '''''''''''''''''''''''
  ' Parameter taken from a user selected row of a GridView
  '
  Dim SomeBudgetID As Integer = gvBudgets.SelectedDataKey.Values(budget_id)

  '''''''''''''''''''''''      
  ' On Instantiation
  '
  Dim R as ActiveReport = New SomeReport(SomeBudgetID)
  R.Run()

  '''''''''''''''''''''''      
  ' Or On Instantiation using "With" syntax
  '
  Dim R as ActiveReport = New SomeReport() With {.BudgetID = SomeBudgetID}
  R.Run()

  '''''''''''''''''''''''
  ' Or After
  '
  Dim R as ActiveReport = New SomeReport()
  R.BudgetID = SomeBudgetID
  R.Run()

So, as I see it, having write-only property in this case

  1. Allows stronger type checking as SqlParameters are kind of generic
  2. More flexibility on creating the report, the report can be instantiated immediately if all parameters are available or added afterward as they become available.
  3. Properties support "With" syntax on instantiation
  4. Is a "getter" really necessary as parameters are known to the user and not altered by the Report?
  5. Since the SqlParameters are a classes and not primitive values, WriteOnly Properties allow for a simpler interface for setting parameters

So that's my thoughts.

Could I convert it to a method instead? sure but the interface seems...less nice

  R2.BudgetID = SomeBudgetID

versus

  R2.SetBudgetID(SomeBudgetID)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.