October 9th, 2025
like2 reactions

The self-assignment principle for Windows Runtime properties applies to default values

Last time, I introduced the self-assignment principle for Windows Runtime properties:

  • Setting a property to its current value is legal and has no effect.

One corollary to this was that setting a property twice to the same value has no effect.

A more interesting corollary is this one:

  • The default value of a property must be a legal value.

If the property value has never been changed from the default, then a self-assignment will assign the default value, and that must succeed.

This second corollary can catch some people who submit API designs in which they propose something like this:

The Doodad­Finder class contains a collection of properties that you can set to narrow the search that occurs when you call Find(). If you want to find Doodads with a specific partner widget, you can set the Doodad­Options.Partner­Widget property to the handle of that partner widget. You may not set the Partner­Widget property to null.

I ask them, “So if I create a brand new Doodad­Finder object and immediately read the Partner­Widget property, what do I get?”

“Oh, since this is a brand new Doodad­Finder object, no partner widget has been specified, so the Partner­Widget is null.”

I pointed out that this violates the “allow self-assignment” rule:

var finder = new DoodadFinder();
finder.PartnerWidget = finder.PartnerWidget; // throws InvalidArgumentException?

You can say that a property may not be null, but you can’t say that and simultaneously default the value to null. You’re saying that the default value is illegal.

The Doodad­Finder should allow the Partner­Widget to be set to null if it is already null.

Indeed, I think that they should allow it to be set back to null, so that there’s a way to undo a prior set. As long as you undo it before calling Find(), then it should behave as if it had never been set.

var finder = new DoodadFinder();
ConfigureFinder(finder); // might set PartnerWidget
finder.PartnerWidget = null; // cancel the partner widget filter

or even

void ConfigureFinderButPreservePartnerWidget(DoodadFinder finder)
{
    var originalPartner = finder.PartnerWidget;
    try {
        ConfigureFinder(finder); // might set the PartnerWidget
    } finally {
        finder.PartnerWidget = originalPartner;
    }
}

Next time, we’ll look at another perhaps-surprising corollary to the self-assignment principle.

Topics
Code

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

2 comments

Sort by :
  • Joshua Hudson · Edited

    I’ve done a few “Default Value Not Legal” versions in the past. The only ones I could justify were of this form:

    The object had a large number of properties; too many for a constructor to be wieldy. (Think GetSaveFileName’s structure for how many.)

    A number of properties had to be initialized for the object to work. The programmer was supposed to immediately initialize them on creating the object before trying to use it.

    The default property value was NULL.

    NULL wasn’t a legal value.

  • Kevin Norris 3 hours ago

    I agree with this principle, but I think there may be a more general way of framing it, that captures a larger space of possible pitfalls:

    A class that has a property named X must be a behavioral subtype of an otherwise-identical class that has a public field named X. That is, if you have some code that works correctly when the property is a public field, that code should also work correctly when the property is a property.

    Obviously, there will be some pathological cases that you don't have to support. Code that would inevitably fail is not "correct," so it...

    Read more