Repository: PowerShell/PowerShell
File: src/System.Management.Automation/engine/CommandCompletion/ExtensibleCompletion.cs (C#)

Code before:
                if (value is null)
                {
                    table.Remove(key);
                }
                else
                {
                    table[key] = value;
                }
            }
        }
    }

    /// <summary>
    /// This attribute is used to specify an argument completions for a parameter of a cmdlet or function
    /// based on string array.
    /// <example>
    ///     [Parameter()]
    ///     [ArgumentCompletions("Option1","Option2","Option3")]
    ///     public string Noun { get; set; }
    /// </example>
    /// </summary>
    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
    public class ArgumentCompletionsAttribute : Attribute
    {
        private readonly string[] _completions;

        /// <summary>
        /// Initializes a new instance of the ArgumentCompletionsAttribute class.
        /// </summary>
        /// <param name="completions">List of complete values.</param>
        /// <exception cref="ArgumentNullException">For null arguments.</exception>
        /// <exception cref="ArgumentOutOfRangeException">For invalid arguments.</exception>
        public ArgumentCompletionsAttribute(params string[] completions)
        {
            if (completions == null)
            {
                throw PSTraceSource.NewArgumentNullException(nameof(completions));
            }

            if (completions.Length == 0)
            {
                throw PSTraceSource.NewArgumentOutOfRangeException(nameof(completions), completions);
            }

            _completions = completions;
        }

        /// <summary>
        /// The function returns completions for arguments.
        /// </summary>
        public IEnumerable<CompletionResult> CompleteArgument(string commandName, string parameterName, string wordToComplete, CommandAst commandAst, IDictionary fakeBoundParameters)

Review comment (suggestion):
I know that I'm suggesting a larger change here, but the pattern is typically `Get-* | Unregister-*`. Treating `null` as remove will potentially hide some design time errors like passing a misspelled variable name.

I definitely understand the need but I'd suggest tackling that separately

Code after:
                {
                    return;
                }

                if (CommandName is null || CommandName.Length is 0)
                {
                    SetKeyValue(completerDictionary, paramName, ScriptBlock);
                    return;
                }

                foreach (string command in CommandName)
                {
                    var key = command?.Trim();
                    key = string.IsNullOrEmpty(key)
                        ? paramName
                        : $"{key}:{paramName}";

                    SetKeyValue(completerDictionary, key, ScriptBlock);
                }
            }

            static void SetKeyValue(Dictionary<string, ScriptBlock> table, string key, ScriptBlock value)
            {
                if (value is null)
                {
                    table.Remove(key);
                }
                else
                {
                    table[key] = value;
                }
            }
        }
    }

    /// <summary>
    /// This attribute is used to specify an argument completions for a parameter of a cmdlet or function
    /// based on string array.
    /// <example>
    ///     [Parameter()]
    ///     [ArgumentCompletions("Option1","Option2","Option3")]
    ///     public string Noun { get; set; }
    /// </example>
    /// </summary>
    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
    public class ArgumentCompletionsAttribute : Attribute
    {
        private readonly string[] _completions;

        /// <summary>
        /// Initializes a new instance of the ArgumentCompletionsAttribute class.