views:

663

answers:

4

In PowerShell 1.0, if I have a cmdlet parameter of an enum type, what is the recommended method for testing whether the user specified that parameter on the cmdlet command line? For example:

MyEnum : int { No = 0, Yes = 1, MaybeSo = 2 }

class DoSomethingCommand : PSCmdlet
...
private MyEnum isEnabled;

[Parameter(Mandatory = false)]
public MyEnum IsEnabled
{
    get { return isEnabled; }
    set { isEnabled = value; }
}

protected override void ProcessRecord()
{
    // How do I know if the user passed -IsEnabled <value> to the cmdlet?
}

Is there any way to do this without having to seed isEnabled with a dummy value? By default it will equal 0, and I don't want to have to seed every parameter or add a dummy value to my enum. I've potentially got many cmdlets with 100's of parameters, there's got to be a better way. This is related to this question but I was looking for a cleaner way of doing this. Thanks.

+1  A: 

Only thing I can see is to modify your enum so that value 0 is named Unknown or something like that.

Problem is that enums are just integers in background and integers are value types. Unfortunate consequence is that they need to have value and that value is 0 by default.

Josip Medved
@Josip, thanks, I see the point. See my comment to x0n.
Jack Straw
+3  A: 

PowerShell aside, it's never good style to use 0 in that way. You should always use 0 for the most appropriate default. In this case, the most appropriate default should be something like "Unset."

Ultimately, this is nothing to do with PowerShell and everything to do with good coding practices for .NET.

  • Oisin
x0n
@x0n: Thank you for your response. Whether using 0 or not for enum values is an arguable point, but either way my existing product does have many 0 values for enums. I guess my broader question is, is this the pattern cmdlet developers use in this situation? Use a default, 'unspecified' value for each parameter, and test against that before applying the parameter values to the object in ProcessRecord()? This could get a bit unwieldy for large products with many parameter types.
Jack Straw
In v2.0 of powershell, a new property was added: this.MyInvocation.BoundParameters where "this" is PSCmdlet. This is a hashtable of key/value pairs of the parameter names and values that were bound to the cmdlet. If your enum was specified, it will be in this dictionary. If it defaulted, it won't be there. I'm not aware of anything other than string hacking that will do the same in v1.0
x0n
x0n, thanks, I saw that 2.0 property. Unfortunately I need to code against 1.0 for now. I think Keith's answer below, using a nullable wrapper, is exactly what I am looking for.
Jack Straw
+2  A: 

In this case, I would use a nullable wrapper around the enum type e.g.

[Parameter(Mandatory = false)]
public MyEnum? IsEnabled { get; set; }

Note the ? modifier on MyEnum. Then you can test if it is set like so:

if (this.IsEnabled.HasValue) { ... }
That's exactly what I was looking for. Thanks. I actually made the local variable, not the property the nullable type, which also works.
Jack Straw
A: 

I know this thread is a little old now, but the best way to do this is to declare your parameter using the SwitchParameter type. Then your users don't have to pass -IsEnabled , they would just add something like -Enabled as a parameter.

You then test the .IsPresent property of your parameter to see if the caller added -Enabled to the call to the cmdlet.

Darren Gosbell
@Darren: that definitely works for bool params, but I was looking for a solution for optional non-bool params. The nullable type seems to work well. Of course PS v2 now has a dictionary of params available in the cmdlet, so that's probably the way to go. Thanks.
Jack Straw