Writing Functions

Avoid Default Values for Mandatory Parameters

Default values for mandatory parameters will always be overwritten, thus they are never used and can cause confusion.

Bad:

function Get-Something
{
    param
    (
        [Parameter(Mandatory = $true)]
        [String]
        $Name = 'My Name'
    )

    ...
}

Good:

function Get-Something
{
    param
    (
        [Parameter(Mandatory = $true)]
        [String]
        $Name
    )

    ...
}

Avoid Default Values for Switch Parameters

Switch parameters have 2 values - there or not there. The default value is automatically $false so it doesn’t need to be declared. If you are tempted to set the default value to $true - don’t - refactor your code instead.

Bad:

function Get-Something
{
    param
    (
        [Switch]
        $MySwitch = $true
    )

    ...
}

Good:

function Get-Something
{
    param
    (
        [Switch]
        $MySwitch
    )

    ...
}

Include the Force Parameter in Functions with the ShouldContinue Attribute

Bad:


Good:


Use ShouldProcess if the ShouldProcess Attribute is Defined

Bad:


Good:


Define the ShouldProcess Attribute if the Function Calls ShouldProcess

Bad:


Good:


Avoid Redefining Reserved Parameters

Reserved Parameters such as Verbose, Debug, etc. are already added to the function at runtime so don’t redefine them. Add the CmdletBinding attribute to include the reserved parameters in your function.

Use the CmdletBinding Attribute on Every Function

The CmdletBinding attribute adds the reserved parameters to your function which is always preferable.

Bad:

function Get-Property
{
    param
    (
        ...
    )
    ...
}

Good:

function Get-Property
{
    [CmdletBinding()]
    param
    (
        ...
    )
    ...
}

Define the OutputType Attribute for All Functions With Output

The OutputType attribute should be declared if the function has output so that the correct error messages get displayed if the function ever produces an incorrect output type.

Bad:

function Get-MyBoolean
{
    [OutputType([Boolean])]
    param ()

    ...

    return $myBoolean
}

Good:

function Get-MyBoolean
{
    [CmdletBinding()]
    [OutputType([Boolean])]
    param ()

    ...

    return $myBoolean
}

Return Only One Object From Each Function

Bad:


Good: