locked
Powershell how to create a delegate RRS feed

  • Question

  • I am not to familar with powershell. I am trying to do something that would be a single line of code in C# but in powershell it is a pain :(

    In the three lines below wow3 throws an error. Anyone know why wow3 throw a type not found error? Does this syntax for delegates only work for built in types?

    $wow1 =[System.Action[int]]
    $wow2 =[MyType]
    $wow3 =[System.Action[MyType]]

    Friday, November 8, 2013 1:25 AM

Answers

  • You might be doing more work that you need to.  PowerShell's engine allows you to pass a ScriptBlock object where the underlying .NET code is expecting a delegate, and handles the conversion for you.  For example, this overload to the Regex.Replace method expects a MatchEvaluator delegate, but you can call it from PowerShell like this:

    $String = '1 2 3 4 5'
    
    [regex]::Replace($String, '\d+', { 2 * [int]$args[0].Value })

    $args[0] is, in this case, the Match object that is passed to a MatchEvaluator delegate.  PowerShell automatically handled converting the integer that the ScriptBlock produced back into the String that the MatchEvaluator is supposed to output.
    • Marked as answer by Yan Li_ Monday, November 25, 2013 2:02 AM
    Friday, November 8, 2013 2:39 PM
  • You shouldn't be using ScriptBlock, because you'll need to re-implement your code in PowerShell, somethig you already have (supposedly) implemented, debugged and working in C#. The best thing to do is keeping simple things simple: add the type MyType and use it.


    ... don't disturb ... life is short, and I have to think what I'll do next ...

    • Marked as answer by Yan Li_ Monday, November 25, 2013 2:02 AM
    Sunday, November 10, 2013 11:23 PM

All replies

  • You might be doing more work that you need to.  PowerShell's engine allows you to pass a ScriptBlock object where the underlying .NET code is expecting a delegate, and handles the conversion for you.  For example, this overload to the Regex.Replace method expects a MatchEvaluator delegate, but you can call it from PowerShell like this:

    $String = '1 2 3 4 5'
    
    [regex]::Replace($String, '\d+', { 2 * [int]$args[0].Value })

    $args[0] is, in this case, the Match object that is passed to a MatchEvaluator delegate.  PowerShell automatically handled converting the integer that the ScriptBlock produced back into the String that the MatchEvaluator is supposed to output.
    • Marked as answer by Yan Li_ Monday, November 25, 2013 2:02 AM
    Friday, November 8, 2013 2:39 PM
  • Hi,

    Just checking in to see if the suggestions were helpful. Please let us know if you would like further assistance.

    TechNet Subscriber Support

    If you are TechNet Subscription user and have any feedback on our support quality, please send your feedback here.


    Regards, Yan Li

    Wednesday, November 13, 2013 2:20 AM
  • David Wyatt, you are my hero today as I have been struggling with this "delegate for PowerShell" question since last week and your answer is exactly what I am looking for. Many thanks !

    On the other hand, to ensure better maintenance and readability (for complex delegate function), I'd suggest, we can use the following method.

    function Delegate-function {
    Param ([int]$p)
    return (2*$p);
    }

    $String = '1 2 3 4 5'

    [regex]::Replace($String, '\d+', {Delegate-function ($args[0].value)})

    This way, the complex logic can be hidden inside the "Delegate-function".

    Sunday, December 14, 2014 6:24 PM
  • Yep, that's one way of doing it. Though I think if I were going to go to the trouble of writing a function instead of using an anonymous script block, I'd probably make the function act just like a MatchEvaluator. Something like this:

    function DoubleIt ([System.Text.RegularExpressions.Match] $Match)
    {
        $value = [int]$Match.Value
        return $value * 2
    }
    
    $String = '1 2 3 4 5'
    
    [regex]::Replace($String, '\d+', $function:DoubleIt)
    

    Monday, December 15, 2014 6:00 AM