Do write-only properties have practical applications?

OopPropertiesLanguage Agnostic

Oop Problem Overview


I don't know why I started thinking about this, but now I can't seem to stop.

In C# - and probably a lot of other languages, I remember that Delphi used to let you do this too - it's legal to write this syntax:

class WeirdClass
{
    private void Hello(string name)
    {
        Console.WriteLine("Hello, {0}!", name);
    }

    public string Name
    {
        set { Hello(name); }
    }
}

In other words, the property has a setter but no getter, it's write-only.

I guess I can't think of any reason why this should be illegal, but I've never actually seen it in the wild, and I've seen some pretty brilliant/horrifying code in the wild. It seems like a code smell; it seems like the compiler should be giving me a warning:

> CS83417: Property 'Name' appears to be completely useless and stupid. Bad programmer! Consider replacing with a method.

But maybe I just haven't been doing this long enough, or have been working in too narrow a field to see any examples of the effective use of such a construct.

Are there real-life examples of write-only properties that either cannot be replaced by straight method calls or would become less intuitive?

Oop Solutions


Solution 1 - Oop

My first reaction to this question was: "What about the java.util.Random#setSeed method?"

I think that write-only properties are useful in several scenarios. For example, when you don't want to expose the internal representation (encapsulation), while allowing to change the state of the object. java.util.Random is a very good example of such design.

Solution 2 - Oop

Code Analysis (aka FxCop) does give you a diagnostic:

> CA1044 : Microsoft.Design : Because > property 'WeirdClass.Name' is write-only, > either add a property getter with an > accessibility that is greater than or > equal to its setter or convert this > property into a method.

Solution 3 - Oop

Write-only properties are actually quite useful, and I use them frequently. It's all about encapsulation -- restricting access to an object's components. You often need to provide one or more components to a class that it needs to use internally, but there's no reason to make them accessible to other classes. Doing so just makes your class more confusing ("do I use this getter or this method?"), and more likely that your class can be tampered with or have its real purpose bypassed.

See "Why getter and setter methods are evil" for an interesting discussion of this. I'm not quite as hardcore about it as the writer of the article, but I think it's a good thing to think about. I typically do use setters but rarely use getters.

Solution 4 - Oop

I have code similar to the following in an XNA project. As you can see, Scale is write-only, it is useful and (reasonably) intuitive and a read property (get) would not make sense for it. Sure it could be replaced with a method, but I like the syntax.

public class MyGraphicalObject
{
    public double ScaleX { get; set; }
    public double ScaleY { get; set; }
    public double ScaleZ { get; set; }

    public double Scale { set { ScaleX = ScaleY = ScaleZ = value; } }

    // more...
}

Solution 5 - Oop

One use for a write-only property is to support setter dependency injection, which is typically used for optional parameters.

Let's say I had a class:

public class WhizbangService {
    public WhizbangProvider Provider { set; private get; }
}

The WhizbangProvider is not intended to be accessed by the outside world. I'd never want to interact with service.Provider, it's too complex. I need a class like WhizbangService to act as a facade. Yet with the setter, I can do something like this:

service.Provider = new FireworksShow();
service.Start();

And the service starts a fireworks display. Or maybe you'd rather see a water and light show:

service.Stop();
service.Provider = new FountainDisplay(new StringOfLights(), 20, UnitOfTime.Seconds);
service.Start();

And so on....

This becomes especially useful if the property is defined in a base class. If you chose construction injection for this property, you'd need to write a constructor overload in any derived class.

public abstract class DisplayService {
    public WhizbangProvider Provider { set; private get; }
}

public class WhizbangService : DisplayService  { }

Here, the alternative with constructor injection is:

public abstract class DisplayService {
    public WhizbangProvider Provider;

    protected DisplayService(WhizbangProvider provider) {
       Provider = provider ?? new DefaultProvider();
    }
}

public class WhizbangService : DisplayService  { 
    public WhizbangService(WhizbangProvider provider) 
      : base(provider) 
    { }
}

This approach is messier in my opinion, because you need to some of the internal workings of the class, specifically, that if you pass null to the constructor, you'll get a reasonable default.

Solution 6 - Oop

In MVP pattern it is common to write a property with a setter on the view (no need for a getter) - whenever the presenter sets it content the property will use that value to update some UI element.

See here for a small demonstration:

public partial class ShowMeTheTime : Page, ICurrentTimeView
{
    protected void Page_Load(object sender, EventArgs e) 
    {
        CurrentTimePresenter presenter = new CurrentTimePresenter(this);
        presenter.InitView();
    }

    public DateTime CurrentTime 
    {
        set { lblCurrentTime.Text = value.ToString(); }
    }
}

The presenter InitView method simply sets the property's value:

public void InitView() 
{
    view.CurrentTime = DateTime.Now;
}

Solution 7 - Oop

Making something write-only is usefulwhenever you're not supposed to read what you write.

For example, when drawing things onto the screen (this is precisely what the Desktop Window Manager does in Windows):
You can certainly draw to a screen, but you should never need to read back the data (let alone expect to get the same design as before).

Now, whether write-only properties are useful (as opposed to methods), I'm not sure how often they're used. I suppose you could imagine a situation with a "BackgroundColor" property, where writing to it sets the background color of the screen, but reading makes no sense (necessarily).
So I'm not sure about that part, but in general I just wanted to point out that there are use cases for situations in which you only write data, and never read it.

Solution 8 - Oop

Although the .NET design guidelines recommend using a method ("SetMyWriteOnlyParameter") instead of a write-only property, I find write-only properties useful when creating linked objects from a serialised representation (from a database).

Our application represents oil-field production systems. We have the system as a whole (the "Model" object) and various Reservoir, Well, Node, Group etc objects.

The Model is created and read from database first - the other objects need to know which Model they belong to. However, the Model needs to know which lower object represents the Sales total. It makes sense for this information to be stored a Model property. If we do not want to have to do two reads of Model information, we need to be able to read the name of Sales object before its creation. Then, subsequently, we set the "SalesObject" variable to point to the actual object (so that, e.g., any change by the user of the name of this object does not cause problems)

We prefer to use a write-only property - 'SalesObjectName = "TopNode"' - rather than a method - 'SetSalesObjectName("TopNode") - because it seems to us that the latter suggests that the SalesObject exists.

This is a minor point, but enough to make us want to use a Write-Only property.

Solution 9 - Oop

As far as I'm concerned, they don't. Every time I've used a write-only property as a quick hack I have later come to regret it. Usually I end up with a constructor or a full property.

Of course I'm trying to prove a negative, so maybe there is something I'm missing.

Solution 10 - Oop

I can't stop thinking about this, either. I have a use case for a "write-only" property. I can't see good way out of it.

I want to construct a C# attribute that derives from AuthorizeAttribute for an ASP.NET MVC app. I have a service (say, IStore) that returns information that helps decide if the current user should be authorized. Constructor Injection won't work, becuase

public AllowedAttribute: AuthorizeAttribute
{
    public AllowedAttribute(IStore store) {...}
    private IStore Store { get; set; }
    ...
}

makes store a positional attribute parameter, but IStore is not a valid attribute parameter type, and the compiler won't build code that is annotated with it. I am forced to fall back on Property Setter Injection.

public AllowedAttribute: AuthorizeAttribute
{
    [Inject] public IStore Store { private get; set; }
    ...
}

Along with all the other bad things about Property Setter instead of Constructor Injection, the service is a write-only property. Bad enough that I have to expose the setter to clients that shouldn't need to know about the implementation detail. It wouldn't do anybody any favors to let clients see the getter, too.

I think that the benefit of Dependency Injection trumps the guidelines against write-only properties for this scenario, unless I am missing something.

Solution 11 - Oop

I just came across that situation when writing a program that reads data from a JSON database (Firebase). It uses Newtonsoft's Json.NET to populate the objects. The data are read-only, i.e., once loaded they won't change. Also, the objects are only deserialized and won't be serialized again. There may be better ways, but this solution just looks reasonable for me.

using Newtonsoft.Json;
// ...

public class SomeDatabaseClass
{
    // JSON object contains a date-time field as string
    [JsonProperty("expiration")]
    public string ExpirationString
    {
        set
        {
		    // Needs a custom parser to handle special date-time formats
            Expiration = Resources.CustomParseDateTime(value);
        }
    }
    
    // But this is what the program will effectively use.
    // DateTime.MaxValue is just a default value
    [JsonIgnore]
    public DateTime Expiration { get; private set; } = DateTime.MaxValue;
	
	// ...
}

Solution 12 - Oop

No, I can' imagine any case where they can't be replaced, though there might people who consider them to be more readable.

Hypothetical case:

CommunicationDevice.Response = "Hello, World" 

instead of

CommunicationDevice.SendResponse("Hello, World")

The major job would be to perform IO side-effects or validation.

Interestingly, VB .NET even got it's own keyword for this weird kind of property ;)

Public WriteOnly Property Foo() As Integer
   Set(value As Integer)
     ' ... '
   End Set
End Property

even though many "write-only" properties from outside actually have a private getter.

Solution 13 - Oop

I recently worked on an application that handled passwords. (Note that I'm not claiming that the following is a good idea; I'm just describing what I did.)

I had a class, HashingPassword, which contained a password. The constructor took a password as an argument and stored it in a private attribute. Given one of these objects, you could either acquire a salted hash for the password, or check the password against a given salted hash. There was, of course, no way to retrieve the password from a HashingPassword object.

So then I had some other object, I don't remember what it was; let's pretend it was a password-protected banana. The Banana class had a set-only property called Password, which created a HashingPassword from the given value and stored it in a private attribute of Banana. Since the password attribute of HashingPassword was private, there was no way to write a getter for this property.

So why did I have a set-only property called Password instead of a method called SetPassword? Because it made sense. The effect was, in fact, to set the password of the Banana, and if I wanted to set the password of a Banana object, I would expect to do that by setting a property, not by calling a method.

Using a method called SetPassword wouldn't have had any major disadvantages. But I don't see any significant advantages, either.

Solution 14 - Oop

I know this has been here for a long time, but I came across it and have a valid (imho) use-case:

When you post parameters to a webapi call from ajax, you can simply try to fill out the parameters class' properties and include validation or whatsoever.

public int MyFancyWepapiMethod([FromBody]CallParams p) {
	return p.MyIntPropertyForAjax.HasValue ? p.MyIntPropertyForAjax.Value : 42;
}

public class CallParams
{
	public int? MyIntPropertyForAjax;
	
	public object TryMyIntPropertyForAjax
	{
		set
		{
			try { MyIntPropertyForAjax = Convert.ToInt32(value); }
			catch { MyIntPropertyForAjax = null; }
		}
	}
}

On JavaScript side you can simply fill out the parameters including validation:

var callparameter = {
	TryMyIntPropertyForAjax = 23
}

which is safe in this example, but if you handle userinput it might be not sure that you have a valid intvalue or something similar.

Solution 15 - Oop

Well, technically there is nothing wrong with a Setter-only property per-se. The Setter could do some validation, and maybe some other methods - public or private - could depend on it.

For example:

class SomeClass {
    private int _someVar;

    SomeClass(int someVar) {
        if(someVar > 0) _someVar = someVar;
    }

    public int SomeVar {
        set { if(value > 0) _someVar = value; }
    }

     public string SomeFunction(){
       return "This is an important function that uses _someVar " + _someVar;
     }
}

So the declaration itself maybe legal and valid. Your method body is a huge code smell though, but that's not the compilers job to care about.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAaronaughtView Question on Stackoverflow
Solution 1 - OopdfaView Answer on Stackoverflow
Solution 2 - OopÐаnView Answer on Stackoverflow
Solution 3 - OopKaleb BraseeView Answer on Stackoverflow
Solution 4 - OopRALView Answer on Stackoverflow
Solution 5 - OopneontapirView Answer on Stackoverflow
Solution 6 - OopBornToCodeView Answer on Stackoverflow
Solution 7 - Oopuser541686View Answer on Stackoverflow
Solution 8 - OopPeter CunninghamView Answer on Stackoverflow
Solution 9 - OopJonathan AllenView Answer on Stackoverflow
Solution 10 - OopSkip SaillorsView Answer on Stackoverflow
Solution 11 - OopRoberto GueleriView Answer on Stackoverflow
Solution 12 - OopDarioView Answer on Stackoverflow
Solution 13 - OopTanner SwettView Answer on Stackoverflow
Solution 14 - Oopz00lView Answer on Stackoverflow
Solution 15 - OopMichael StumView Answer on Stackoverflow