Skip to content

Parameters Should Support Mutual Exclusion Natively #5175

@markekraus

Description

@markekraus

Problem

Parameter sets are great for grouping parameters into sets that work together. This can, to some degree, also be used to make parameters exclusive. The problem arises when you have mutually exclusive parameters that need to exist in all parameter sets. The current implementation would require creating additional parameter sets to accommodate the actual parameter sets and the mutually exclusive parameters.

For very simplistic demonstration, lets say you have a New-Widget:

function New-Widget {
    [CmdletBinding()]
    param (
        [Parameter(ParameterSetName="Size")]
        [int]$Height,
        [Parameter(ParameterSetName="Size")]
        [int]$Width,
        [Parameter(ParameterSetName="Size")]
        [int]$Length,

        [Parameter(ParameterSetName="Color")]
        [int]$Red,
        [Parameter(ParameterSetName="Color")]
        [int]$Green,
        [Parameter(ParameterSetName="Color")]
        [int]$Blue
    )
}

Widgets can be defined either by color or size. Now, let say that all widgets, regardless of begin defined by size or color, can either have a flavor or a sound but not both. Currently, to accommodate this you would need to do the following:

function New-Widget {
    [CmdletBinding()]
    param (
        [Parameter(ParameterSetName="SizeFlavor")]
        [Parameter(ParameterSetName="SizeSound")]
        [int]$Height,
        [Parameter(ParameterSetName="SizeFlavor")]
        [Parameter(ParameterSetName="SizeSound")]
        [int]$Width,
        [Parameter(ParameterSetName="SizeSound")]
        [Parameter(ParameterSetName="SizeFlavor")]
        [int]$Length,

        [Parameter(ParameterSetName="ColorFlavor")]
        [Parameter(ParameterSetName="ColorSound")]
        [int]$Red,
        [Parameter(ParameterSetName="ColorSound")]
        [Parameter(ParameterSetName="ColorFlavor")]
        [int]$Green,
        [Parameter(ParameterSetName="ColorSound")]
        [Parameter(ParameterSetName="ColorFlavor")]
        [int]$Blue,

        [Parameter(ParameterSetName="SizeFlavor")]
        [Parameter(ParameterSetName="ColorFlavor")]
        [string]$Flavor,

        [Parameter(ParameterSetName="SizeSound")]
        [Parameter(ParameterSetName="ColorSound")]
        [string]$Sound
    )
}

This can get wildly out of hand if you have a third or fourth set of mutually exclusive parameters. This becomes difficult to maintain and to add additional parameters. Another option is to have logic in the body of the function to check for mutually exclusive Parameters at the cost of the mutual exclusion not being as discoverable.

In some instances you may be able to refactor into additional cmdlets or make use of custom types. But that doesn't always work for command line utilities meant to ease user burden at the cost of code complexity.

Proposal

I propose that parameters should support mutual exclusion natively. I don't have a solid implementation plan, but one idea would be to add a Parameter Attribute property like ParameterMutexName. Using the example above it would work like this:

function New-Widget {
    [CmdletBinding()]
    param (
        [Parameter(ParameterSetName="Size")]
        [int]$Height,
        [Parameter(ParameterSetName="Size")]
        [int]$Width,
        [Parameter(ParameterSetName="Size")]
        [int]$Length,

        [Parameter(ParameterSetName="Color")]
        [int]$Red,
        [Parameter(ParameterSetName="Color")]
        [int]$Green,
        [Parameter(ParameterSetName="Color")]
        [int]$Blue,

        [Parameter(ParameterSetName="Size", ParameterMutexName="FlavorOrSound")]
        [Parameter(ParameterSetName="Color", ParameterMutexName="FlavorOrSound")]
        [string]$Flavor,
        [Parameter(ParameterSetName="Size", ParameterMutexName="FlavorOrSound")]
        [Parameter(ParameterSetName="Color", ParameterMutexName="FlavorOrSound")]
        [string]$Sound
    )
}

Parameter binding logic would then check if more than one parameter is supplied in a ParameterMutexName and throw. This is flexible enough to accommodate parameters being exclusive in one set while not exclusive in other sets. This could also accommodate multiple Mutex sets within a parameter set.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Issue-Discussionthe issue may not have a clear classification yet. The issue may generate an RFC or may be reclassifIssue-Enhancementthe issue is more of a feature request than a bugResolution-No ActivityIssue has had no activity for 6 months or more

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions