3
\$\begingroup\$

I am playing with learning PowerShell classes, and I have a validation situation that kind of lends itself to Enums, as shown in the first example. With Enum

Enum pxPathType {
 FileSystem_Folder = 0
 FileSystem_File = 1
 Registry_Key = 2
 Registry_Property = 3
}
class PxConstant {
 # Static Properties
 static [string] $RegExPathWithWildcard = '\\\*\.\*$|\\\*|\\.\.\*$|\*\.(\?[a-zA-Z0-9\?]{2}|[a-zA-Z0-9\?]\?[a-zA-Z0-9\?]|[a-zA-Z0-9\?]{2}\?)$|\\[^\\]*\.(\?[a-zA-Z0-9\?]{2}|[a-zA-Z0-9\?]\?[a-zA-Z0-9\?]|[a-zA-Z0-9\?]{2}\?)$|\\[^\\]*\.\*$'
}
class PxPath {
 # Properties
 [string]$Type = $null
 # Constructors
 PxPath ([string]$path) {
 $this.Type = [PxPath]::PathType($path)
 }
 PxPath ([string]$path, [string]$pathType) {
 #$pathTypeEnum = try {
 $this.Type = try {
 [pxPathType] $pathType 
 } catch { 
 Throw "Not a valid path type: $pathType"
 }
 }
 static [String] PathType ([String]$path) {
 [string]$pathType = $null
 if ($path -match [PxConstant]::RegExPathWithWildcard) {
 $pathWithoutWildcard = $path -replace [regex]::escape($matches[0]), ''
 Write-Host $pathWithoutWildcard
 }
 return $pathType
 }
}
$pathType = 'FileSystem_Folders'
$path = try {
 [PxPath]::New("C:\", $pathType)
} catch {
 Write-Host "$($_.Exception.Message)"
}
$path = try {
 [PxPath]::New("\\Server\Folder\*")
} catch {
 Write-Host "$($_.Exception.Message)"
}

The issue I have is that the Enum is only EVER used in the PxPath class, and I feel like that means I should have the Enum in the class, so it's self contained. However, PS5 doesn't allow an Enum in a class. The workaround I have come up with is to instead use an array as a hidden Property of the class instead, as in this second example.

With Array in Class

class PxConstant {
 # Static Properties
 static [string] $RegExPathWithWildcard = '\\\*\.\*$|\\\*|\\.\.\*$|\*\.(\?[a-zA-Z0-9\?]{2}|[a-zA-Z0-9\?]\?[a-zA-Z0-9\?]|[a-zA-Z0-9\?]{2}\?)$|\\[^\\]*\.(\?[a-zA-Z0-9\?]{2}|[a-zA-Z0-9\?]\?[a-zA-Z0-9\?]|[a-zA-Z0-9\?]{2}\?)$|\\[^\\]*\.\*$'
}
class PxPath {
 # Properties
 hidden [string[]]$validPathTypes = @('FileSystem_Folder', 'FileSystem_File', 'Registry_Key', 'Registry_Property')
 [string]$Type = $null
 # Constructors
 PxPath ([string]$path) {
 $this.Type = [PxPath]::PathType($path)
 }
 PxPath ([string]$path, [string]$pathType) {
 if ($this.validPathTypes -contains $pathType) {
 $this.Type = $pathType 
 } else {
 Throw "Not a valid path type: $pathType"
 }
 }
 static [String] PathType ([String]$path) {
 [string]$pathType = $null
 if ($path -match [PxConstant]::RegExPathWithWildcard) {
 $pathWithoutWildcard = $path -replace [regex]::escape($matches[0]), ''
 Write-Host $pathWithoutWildcard
 }
 return $pathType
 }
}
$pathType = 'FileSystem_Folders'
$path = try {
 [PxPath]::New("C:\", $pathType)
} catch {
 Write-Host "$($_.Exception.Message)"
}
$path = try {
 [PxPath]::New("\\Server\Folder\*")
} catch {
 Write-Host "$($_.Exception.Message)"
}

I'm wondering if there is a performance or functional argument for one over the other? Or perhaps a strong Best Practice argument in favor? Or is this coders choice really?

asked Mar 7, 2020 at 16:34
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

The best argument for using an enum in this context is the ability to:

  1. Early input validation
  2. Allowing users to discover valid inputs

In order to take advantage of that, your first example needs a slight change to use the enum type as the parameter type:

class PxPath {
 PxPath ([string]$path, [pxPathType]$pathType) {
 # if user input a string that doesn't correspond 
 # to a [pxPathType] name, we won't even get this far!
 }
}

Now, your user has the option to pass either a [pxPathType] value or a corresponding string value:

$pxPath = [PxPath]::new("some\path", [pxPathType]::FileSystem_Folder)
# or
$pxPath = [PxPath]::new("some\path", 'FileSystem_Folder')

But this would fail even before we reach inside the constructor:

$pxPath = [PxPath]::new("some\path", 'not_a_valid_enum_name')
answered Apr 30, 2020 at 10:03
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.