Powershell, OOP, Why return $false does not exit Class Method

Viewed 60

in Powershell 5

I do not understand, when debugging this code, why when the string " of the" is matched at the end of the main string, the method does not perform exit from the Class Method and continues to iterate.

Seems contra-intuitive to me.

Must I use the auxiliary variable and a label combined with break command?

something like here:

:JUMPASFOX foreach ($i in (1..10)) {
...{break JUMPASFOX}

I thought return $false anywhere causes exit. I cannot reconcile that my code does not work.

Class EndFinder {
    [string[]]$Exclusions_End_Text=@(" of", " of the", " of a", "for a", "for the", " in", " the")
    EndFinder(){}

    [boolean]Contains_Exclusion_At_The_End ([string]$ClipText) {
       #$found=$false
       $this.Exclusions_End_Text |foreach { 
            $exclusion_length=$_.Length
            $clip_length=$ClipText.Length
            if ($exclusion_length -lt $clip_length) {
               $tailing=$ClipText.Substring($clip_length-$exclusion_length,$exclusion_length)
               if ($tailing -eq $_) {
                    #$found=$true
                    return $true
               }
            }
       }
       return $false
       #return $found
    }
}

$kb=[EndFinder]::New()
$kb.Contains_Exclusion_At_The_End("big problem of the")
1 Answers

As Mathias R. Jessen points out in his comment, the return keyword when used in the scope of a cmdlet such as ForEach-Object will go to the next iteration, similar to what continue would do if it was a loop (for, foreach, while, etc).

  • Goes to next iteration when the condition is met:
0..4 | ForEach-Object {
    if($_ % 2) {
        return 'Odd'
    }
    'Even'
}

Even
Odd
Even
Odd
Even

# Same behavior with script block:

0..4 | & {
    process
    {
        if($_ % 2) {
            return 'Odd'
        }
        'Even'
    }
}
  • Stops the iteration:
foreach($i in 0..4) {
    if($i % 2) {
        return 'Odd'
    }
    'Even'
}

Even
Odd

I'm assuming you're trying to see if the string provided to your method ends with any of the $Exclusions_End_Text strings from your class property. If that's the case, this should do it:

Class EndFinder {
    hidden [string[]]$Exclusions_End_Text = @(
        " of", " of the", " of a", "for a", "for the", " in", " the"
    )

    # EndFinder(){} => Constructor is not needed here, PS does this by default.

    [boolean] Contains_Exclusion_At_The_End ([string]$ClipText)
    {
        foreach($i in $this.Exclusions_End_Text)
        {
            if($ClipText.EndsWith($i))
            {
                return $true
            }
        }
        return $false
    }
}

$kb = [EndFinder]::New()
$kb.Contains_Exclusion_At_The_End('big problem of the') # => True
$kb.Contains_Exclusion_At_The_End('not ending with any $Exclusions_End_Text') # => False

I would personally use a static method in this case, I believe it's more appropriate for what you're trying to accomplish:

Class EndFinder {
    static [boolean] Contains_Exclusion_At_The_End ([string]$ClipText)
    {
        $Exclusions_End_Text = @(
            " of", " of the", " of a", "for a", "for the", " in", " the"
        )

        foreach($i in $Exclusions_End_Text)
        {
            if($ClipText.EndsWith($i))
            {
                return $true
            }
        }
        return $false
    }
}

[EndFinder]::Contains_Exclusion_At_The_End('big problem of the')
[EndFinder]::Contains_Exclusion_At_The_End('not ending with any $Exclusions_End_Text')
Related