Search code examples
powershellclass-methodtry-catch-finally

How does one use the Try-Catch-Finally block in a class method?


I get contradictory error messages when trying to set up a try-catch-finally block in a class method which returns a string.

My code is:

class exampleClass {    
    [string]Create() {
        try {
            $rsa_Base64 = "string"            
            return $rsa_Base64
        }
        catch {
            {...}
        }
        finally {
            Remove-Item -Path $env:TEMP\test.txt
        }        
    }
}

In this situation I get the error: Not all code path returns value within method.

If I move the return statement to the finally block I get the error: Flow of control cannot leave a Finally block.

I want to add the finally block in order to ensure the removal of created files in the try statement.


Solution

  • You can avoid the problem by using the return statement unconditionally, outside the try / catch/ finally statement:

    class exampleClass {    
        [string]Create() {
            $rsa_Base64 = ''  # must initialize the variable
            try {
                $rsa_Base64 = "string"            
            }
            catch {
                {...}
            }
            finally {
                Remove-Item -Path $env:TEMP\test.txt
            }
            return $rsa_Base64
        }
    }
    

    Note the use of '' to initialize the variable; using $null would ultimately not be effective, because the method is [string]-typed, and PowerShell doesn't support $null in [string] values and converts them to '' (the empty string) - see this answer for more information.


    More properly, however, you should ensure that your catch branch contains a scope-exiting flow-control statement as well[1], namely return or throw (while exit technically works too, it should only be used in script files, as it exits the session as a whole):

    class exampleClass {    
        [string]Create() {
            try {
                $rsa_Base64 = "string"            
                return $rsa_Base64
            }
            catch {
                {...}
                return ''  # must exit the method from this block too 
            }
            finally {
                Remove-Item -Path $env:TEMP\test.txt
            }        
        }
    }
    

    [1] By contrast, the finally block not only doesn't need a scope-exiting statement, by design it doesn't support any. The reason is that this block is run outside the normal flow of control and is intended solely for cleanup.