4

I'd like to cast a .NET object to another .NET type, but:

  • The target .NET type (class) is stored in a variable
  • I don't want to use the -as PowerShell operator
  • I am using complex, non-primitive types

How would you achieve this?

For example, this is the "PowerShell" way to do it, but I don't want to use -as:

$TargetType = [System.String]; # The type I want to cast to
1 -as $TargetType;             # Cast object as $TargetType

Unfortunately, this does not work:

$TargetType = [System.String];
[$TargetType]1;

.. because PowerShell does not allow the use of variables inside the square brackets, in this scenario.

I am imagining something like:

$TargetType = [System.String];
$TargetType.Cast(1); # Does something like this exist in the .NET framework?

Can it be done with .NET method syntax? Is there a static method that does this?

2
  • 3
    Whenever someone says "X works but I don't want to use X". I instantly think of an XY Problem situation. What is your actual goal and why does the -as method not work for you? Commented Apr 1, 2014 at 19:02
  • I agree with your sentiment. The reasoning behind the question is that I try to ensure that my PowerShell coding can translate to C# (and other, similar languages) as closely as possible. Commented Apr 1, 2014 at 19:35

1 Answer 1

7

You can roughly emulate a cast using the following method:

[System.Management.Automation.LanguagePrimitives]::ConvertTo($Value, $TargetType)

A true cast may behave differently than the above method for dynamic objects that provide their own conversions. Otherwise, the only other difference I can think of is performance - a true cast may perform better because of optimizations not available in the ConvertTo static method.

To precisely emulate a cast, you'll need to generate a script block with something like:

function GenerateCastScriptBlock
{
    param([type]$Type)

    [scriptblock]::Create('param($Value) [{0}]$Value' -f
        [Microsoft.PowerShell.ToStringCodeMethods]::Type($Type))
}

You can then assign this script block to a function or invoke it directly, e.g.:

(& (GenerateCastScriptBlock ([int])) "42").GetType()
Sign up to request clarification or add additional context in comments.

5 Comments

Perhaps I should have clarified this in the question a bit more. Is there a way to do it more generically, without relying on the PowerShell managed libraries?
That's a very different question. Programming languages define valid conversions. For example, conversions in PowerShell or C++/CLI can be different than what C# might allow. I think you need to specify what exactly you want to convert generically before looking for a simple API that does what you want.
I forgot that C# had an as operator. I guess maybe my question was asked in vain. I thought that I had previously come across an API that did what I was looking for, but it may have been something slightly different. Marking yours as the answer for now.
Your solution was exactly what I was looking for!
Would you mind sharing how you use the GenerateCastScriptBlock to assign the value to a variable? E.g. how do you assign the value of 42 to a variable, say, $x? And would it be possible to do the same for arrays? Say, convert a string '@("x","y","z")' to an array type variable $y.

Your Answer

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