Write-Only properties, what's the point? [duplicate]

I understand why you would want to use a read-only property using the following syntax:

private int _MyInt;
public int MyInt
{
  get { return _MyInt; }
}

This example probably isn't the best one because I think that read-only properties really shine in conjunction with a readonly variable, but that's beside the point. What I don't understand is why use a write-only property using the following syntax:

private int _MyInt;
public int MyInt
{
  set { _MyInt = value; }
}

This is how read-only properties are described in various books and tutorials. If you set the variable, you would conceptually read it at some point, at least internally to the class, but to read it even internally within the class you would do so by accesssing _MyInt which I feel violates the spirit of encapsulation which properties try to enforce. Instead, why wouldn't you just use the full power of the property with different access modifies for accessing it as such:

private int _MyInt;
public int MyInt
{
  set { _MyInt = value; }
  private get { return _MyInt; }
}

Which of course can just be written

public int MyInt { set; private get; }

You still get the encapsulation, but restrict other classes from access, so its still write-only to outside classes.

Unless there is a case where you honestly would want to assign to a variable but never actually access it, in which case I would definitely be curious about when this need would arise.


Solution 1:

I have never come across a valid use-case for a write-only property. Honestly, if there is a valid use-case for a write-only property I think it is safe to say that the solution is poorly designed.

If you need "write-only" semantics you should use a method. For instance, another user has found an example of a user object that uses a write-only property to set a password. This is a bad design:

class User
{
    public string Password
    {
        set { /* password encryption here */ }
    }
}

Ugh. This is much better:

class User
{
    public void SetPassword(string password)
    {
        /* password encryption here */
    }
}

See, a read/write property is a set of methods that are designed to masquerade as a field. They look and feel like a field. It is for this reason that a read-only property makes sense because we are used to having fields and variables that we can read but cannot change. However there isn't a corresponding field or variable construct that is writable but not readable.

This is why I believe that creating an API that employs write-only properties is bad practice. It runs counter-intuitive to what I believe is the main goal of the property syntax in C#.

Edit: More philosophy... I believe that classes serve a functional purpose: they provide a container for related data to be held and manipulated. Take our User class for example - this class will hold all pieces of information that pertain to a user in the system. We collect all these pieces of data and give them a single name: user. In this way we use classes to create abstractions. User is an abstraction that allows us to reason about all the individual pieces of data that comprise a user (password, name, birthday, etc.).

Now there are good abstractions and there are bad abstractions. I believe that write-only properties are bad abstractions because you are allowing someone to input data and not read it. Why would you disallow this? Most likely because the information that has been passed in has been transformed in some way that makes it unreadable to the passer.

So this means that a write-only property by definition must create side-effects that the caller cannot see (because if they could see them then there would be no reason to make the property write-only). The best construct in the C# language for setting a value with side-effects is the method.

I would highly recommend not using write-only properties because consumers of your API will find them confusing and frustrating. Even if you find a valid use-case for this syntax it doesn't justify its use.


Edit: Here is official recommendation from .Net Framework Design Guidelines for Developing Class Libraries -> Member Design Guidelines -> Property Design

Do not provide set-only properties.

If the property getter cannot be provided, use a method to implement the functionality instead. The method name should begin with Set followed by what would have been the property name...

Solution 2:

Interesting question.

After some Googling, this is all I could find: a write-only property could be used to set a password on a User object. Since passwords are usually stored in hashed form, there is (and should be) no way to retrieve a password after it has been set.

Solution 3:

One use for a write-only property is to support setter dependency injection.

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....

Solution 4:

A common case I can see is if you only wanted a caller to be able to obtain a transformed version of your property. For example:

public int MyInt { set; }
public string MyIntAsString 
{ 
   get { return this.MyInt.ToString(); } 
}

Obviously, this isn't a real example, but you get the picture.

EDIT:

After reading Thomas' example use case, then a real "transformation" type scenario could be to retrieve an encrypted version of the write-only property:

private string password;

public string ClearPassword { set { this.password = value; }
public string EncryptedPassword
{
   get { return Encrypt(password); }
}