Windows Vista Forums
Vista Forums Home Join Vista Forums Donate Vista Tutorials Tags

Welcome to Vista Forums we are your forum to discuss Windows Vista x64 and x86 systems. Whether you need help or just want to post an idea you have on Vista, this is the forum for you.
Register at Vista forums...the world biggest Windows Vista resource Join Vista Forums Now

Go Back   Vista Forums > Microsoft Technical Newsgroups > PowerShell

Typecasting issue

Update your Vista Drivers Update Your Drivers Now!!
Closed Thread
 
Thread Tools Display Modes
Old 04-11-2007   #1 (permalink)
Jonathan
Guest


 

Typecasting issue

I am having an issue with casting a double to an int32 inside a for loop.
Executing this code:

PS> for ($i = 0; $i -le 5; $i++) {$Value = ([System.Int32]([Math]::Pow(2,
$i))); Write-Host "$i -> $Value [$($Value.gettype().fullname)]"}

I get the results:

0 -> 1 [System.Int32]
1 -> 2 [System.Double]
2 -> 4 [System.Double]
3 -> 8 [System.Double]
4 -> 16 [System.Double]
5 -> 32 [System.Double]

When I execute the type conversion of the output of [Math]::Pow() at the PS
prompt, I get different results:

PS> $Value = ([System.Int32]([Math]::Pow(2, 5)))
PS> Write-Host "5 -> $Value [$($Value.gettype().fullname)]"
5 -> 32 [System.Int32]

Is this a bug or am I missing something in my for loop?

Thanks

My System SpecsSystem Spec
Old 04-11-2007   #2 (permalink)
Brandon Shell
Guest


 

Re: Typecasting issue

Worked for me if I moved the [system.int32] in front of value.

Like this
for ($i = 0; $i -le 5; $i++) {[System.Int32]$Value = (([Math]::Pow(2,$i)));
Write-Host "$i -> $Value [$($Value.gettype().fullname)]"}


"Jonathan" <Jonathan@discussions.microsoft.com> wrote in message
news:6F4ED326-8217-430D-A0E7-8ED49A1D9FB1@microsoft.com...
>I am having an issue with casting a double to an int32 inside a for loop.
> Executing this code:
>
> PS> for ($i = 0; $i -le 5; $i++) {$Value = ([System.Int32]([Math]::Pow(2,
> $i))); Write-Host "$i -> $Value [$($Value.gettype().fullname)]"}
>
> I get the results:
>
> 0 -> 1 [System.Int32]
> 1 -> 2 [System.Double]
> 2 -> 4 [System.Double]
> 3 -> 8 [System.Double]
> 4 -> 16 [System.Double]
> 5 -> 32 [System.Double]
>
> When I execute the type conversion of the output of [Math]::Pow() at the
> PS
> prompt, I get different results:
>
> PS> $Value = ([System.Int32]([Math]::Pow(2, 5)))
> PS> Write-Host "5 -> $Value [$($Value.gettype().fullname)]"
> 5 -> 32 [System.Int32]
>
> Is this a bug or am I missing something in my for loop?
>
> Thanks


My System SpecsSystem Spec
Old 04-11-2007   #3 (permalink)
Jonathan
Guest


 

Re: Typecasting issue

Interesting. That works in my case as well.

However, I am interested in an explanation of why, in my original example,
the first iteration of the loop always converts the type no matter the
starting value of $i, but subsequent iterations do not.

I'm also interested in why PowerShell's automatic type conversion isn't
working in this case. I'm using this code in defining an enum:

for ($i = 0; $i -lt $args.length; $i++) {
[System.Int32]$Value = [Math]::Pow(2, $i)
$null = $EnumBuilder.DefineLiteral($args[$i], $Value)
}

If I don't explicitly cast $Value to an Int, the method call to
DefineLiteral throws an exception "Constant does not match the defined type".

Thanks

"Brandon Shell" wrote:

> Worked for me if I moved the [system.int32] in front of value.
>
> Like this
> for ($i = 0; $i -le 5; $i++) {[System.Int32]$Value = (([Math]::Pow(2,$i)));
> Write-Host "$i -> $Value [$($Value.gettype().fullname)]"}
>
>
> "Jonathan" <Jonathan@discussions.microsoft.com> wrote in message
> news:6F4ED326-8217-430D-A0E7-8ED49A1D9FB1@microsoft.com...
> >I am having an issue with casting a double to an int32 inside a for loop.
> > Executing this code:
> >
> > PS> for ($i = 0; $i -le 5; $i++) {$Value = ([System.Int32]([Math]::Pow(2,
> > $i))); Write-Host "$i -> $Value [$($Value.gettype().fullname)]"}
> >
> > I get the results:
> >
> > 0 -> 1 [System.Int32]
> > 1 -> 2 [System.Double]
> > 2 -> 4 [System.Double]
> > 3 -> 8 [System.Double]
> > 4 -> 16 [System.Double]
> > 5 -> 32 [System.Double]
> >
> > When I execute the type conversion of the output of [Math]::Pow() at the
> > PS
> > prompt, I get different results:
> >
> > PS> $Value = ([System.Int32]([Math]::Pow(2, 5)))
> > PS> Write-Host "5 -> $Value [$($Value.gettype().fullname)]"
> > 5 -> 32 [System.Int32]
> >
> > Is this a bug or am I missing something in my for loop?
> >
> > Thanks

>
>

My System SpecsSystem Spec
Old 04-11-2007   #4 (permalink)
Brandon Shell
Guest


 

Re: Typecasting issue

Unfortunately... I can only speculate why. I just know from my experience
that you have to type the variable instead of the results.

"Jonathan" <Jonathan@discussions.microsoft.com> wrote in message
news:02079A14-4438-4835-9FD1-2438F493829A@microsoft.com...
> Interesting. That works in my case as well.
>
> However, I am interested in an explanation of why, in my original example,
> the first iteration of the loop always converts the type no matter the
> starting value of $i, but subsequent iterations do not.
>
> I'm also interested in why PowerShell's automatic type conversion isn't
> working in this case. I'm using this code in defining an enum:
>
> for ($i = 0; $i -lt $args.length; $i++) {
> [System.Int32]$Value = [Math]::Pow(2, $i)
> $null = $EnumBuilder.DefineLiteral($args[$i], $Value)
> }
>
> If I don't explicitly cast $Value to an Int, the method call to
> DefineLiteral throws an exception "Constant does not match the defined
> type".
>
> Thanks
>
> "Brandon Shell" wrote:
>
>> Worked for me if I moved the [system.int32] in front of value.
>>
>> Like this
>> for ($i = 0; $i -le 5; $i++) {[System.Int32]$Value =
>> (([Math]::Pow(2,$i)));
>> Write-Host "$i -> $Value [$($Value.gettype().fullname)]"}
>>
>>
>> "Jonathan" <Jonathan@discussions.microsoft.com> wrote in message
>> news:6F4ED326-8217-430D-A0E7-8ED49A1D9FB1@microsoft.com...
>> >I am having an issue with casting a double to an int32 inside a for
>> >loop.
>> > Executing this code:
>> >
>> > PS> for ($i = 0; $i -le 5; $i++) {$Value =
>> > ([System.Int32]([Math]::Pow(2,
>> > $i))); Write-Host "$i -> $Value [$($Value.gettype().fullname)]"}
>> >
>> > I get the results:
>> >
>> > 0 -> 1 [System.Int32]
>> > 1 -> 2 [System.Double]
>> > 2 -> 4 [System.Double]
>> > 3 -> 8 [System.Double]
>> > 4 -> 16 [System.Double]
>> > 5 -> 32 [System.Double]
>> >
>> > When I execute the type conversion of the output of [Math]::Pow() at
>> > the
>> > PS
>> > prompt, I get different results:
>> >
>> > PS> $Value = ([System.Int32]([Math]::Pow(2, 5)))
>> > PS> Write-Host "5 -> $Value [$($Value.gettype().fullname)]"
>> > 5 -> 32 [System.Int32]
>> >
>> > Is this a bug or am I missing something in my for loop?
>> >
>> > Thanks

>>
>>


My System SpecsSystem Spec
Old 04-11-2007   #5 (permalink)
Ryan Milligan
Guest


 

Re: Typecasting issue

Oh, my...I do believe you've found a pretty serious bug in method
invocation. Check out the code for
System.Management.Automation.Parser+MethodCallNode.Execute() in Reflector
(http://www.aisto.com/roeder/dotnet/), which is called when it comes time to
execute your [Math]::Pow() method:

internal override object Execute(Array input, Pipe outputPipe)
{
using (IDisposable disposable =
ParseTreeNode.tracer.TraceMethod(base.NodeToken))
{
object[] paramArray = this.arguments.Execute(null, null) as
object[];
object originalResult = this.targetExpression.Execute(input, null);
if (this.useCachedMethodInfo)
{
return ParserOps.CallMethod(base.NodeToken, null,
base.NodeToken.TokenText, paramArray, this.staticMember, this.targetMethod,
AutomationNull.Value);
}
object obj3 = InvokeMethod(base.NodeToken, originalResult,
this.staticMember, paramArray, this.typeConstraint, ref this.targetMethod);
if (this.staticMember && (this.targetExpression is
Parser.UnaryOperatorNode))
{
this.useCachedMethodInfo = true;
}
return obj3;
}
}

Notice that if the method information has already been cached, it will call
InvokeMethod(). Then, if we're doing a static invocation (which we are, in
this case), the data gets cached. Next time we come through, because we're
invoking a static method, the data's been cached, so we go straight to
CallMethod(), which is also called by InvokeMethod(). However, at the bottom
of InvokeMethod() is this:

foreach (TypeLiteral literal in typeConstraint)
{
obj3 = Parser.ConvertTo(obj3, literal.Type, NodeToken);
}

I believe this is the problem...it seems like this little block of code
really needs to be at the end of CallMethod(), not InvokeMethod(), or it
only gets triggered the first time through for static invocations. I
confirmed that this scenario works fine for non-static methods by simply
doing this:

ls | % { ([string]$_.LastWriteTime).GetType().FullName }

And it printed out System.String for all of them. Then, I change it to this:

ls | % {
([string][System.IO.File]::GetLastWriteTime($_.FullName)).GetType().FullName
}

And it printed out System.String for the first, then System.DateTime for the
rest. Good catch!

-- Ryan Milligan

"Jonathan" <Jonathan@discussions.microsoft.com> wrote in message
news:02079A14-4438-4835-9FD1-2438F493829A@microsoft.com...
> Interesting. That works in my case as well.
>
> However, I am interested in an explanation of why, in my original example,
> the first iteration of the loop always converts the type no matter the
> starting value of $i, but subsequent iterations do not.
>
> I'm also interested in why PowerShell's automatic type conversion isn't
> working in this case. I'm using this code in defining an enum:
>
> for ($i = 0; $i -lt $args.length; $i++) {
> [System.Int32]$Value = [Math]::Pow(2, $i)
> $null = $EnumBuilder.DefineLiteral($args[$i], $Value)
> }
>
> If I don't explicitly cast $Value to an Int, the method call to
> DefineLiteral throws an exception "Constant does not match the defined
> type".
>
> Thanks
>
> "Brandon Shell" wrote:
>
>> Worked for me if I moved the [system.int32] in front of value.
>>
>> Like this
>> for ($i = 0; $i -le 5; $i++) {[System.Int32]$Value =
>> (([Math]::Pow(2,$i)));
>> Write-Host "$i -> $Value [$($Value.gettype().fullname)]"}
>>
>>
>> "Jonathan" <Jonathan@discussions.microsoft.com> wrote in message
>> news:6F4ED326-8217-430D-A0E7-8ED49A1D9FB1@microsoft.com...
>> >I am having an issue with casting a double to an int32 inside a for
>> >loop.
>> > Executing this code:
>> >
>> > PS> for ($i = 0; $i -le 5; $i++) {$Value =
>> > ([System.Int32]([Math]::Pow(2,
>> > $i))); Write-Host "$i -> $Value [$($Value.gettype().fullname)]"}
>> >
>> > I get the results:
>> >
>> > 0 -> 1 [System.Int32]
>> > 1 -> 2 [System.Double]
>> > 2 -> 4 [System.Double]
>> > 3 -> 8 [System.Double]
>> > 4 -> 16 [System.Double]
>> > 5 -> 32 [System.Double]
>> >
>> > When I execute the type conversion of the output of [Math]::Pow() at
>> > the
>> > PS
>> > prompt, I get different results:
>> >
>> > PS> $Value = ([System.Int32]([Math]::Pow(2, 5)))
>> > PS> Write-Host "5 -> $Value [$($Value.gettype().fullname)]"
>> > 5 -> 32 [System.Int32]
>> >
>> > Is this a bug or am I missing something in my for loop?
>> >
>> > Thanks

>>
>>



My System SpecsSystem Spec
Old 04-11-2007   #6 (permalink)
Ryan Milligan
Guest


 

Re: Typecasting issue

Er...notice that if the method data has *not* already been cached, that is.

-- Ryan Milligan

"Ryan Milligan" <Ceiled@hotmail.com> wrote in message
news:5oednduhveraD4DbnZ2dnUVZ_uuqnZ2d@comcast.com...
> Oh, my...I do believe you've found a pretty serious bug in method
> invocation. Check out the code for
> System.Management.Automation.Parser+MethodCallNode.Execute() in Reflector
> (http://www.aisto.com/roeder/dotnet/), which is called when it comes time
> to execute your [Math]::Pow() method:
>
> internal override object Execute(Array input, Pipe outputPipe)
> {
> using (IDisposable disposable =
> ParseTreeNode.tracer.TraceMethod(base.NodeToken))
> {
> object[] paramArray = this.arguments.Execute(null, null) as
> object[];
> object originalResult = this.targetExpression.Execute(input, null);
> if (this.useCachedMethodInfo)
> {
> return ParserOps.CallMethod(base.NodeToken, null,
> base.NodeToken.TokenText, paramArray, this.staticMember,
> this.targetMethod, AutomationNull.Value);
> }
> object obj3 = InvokeMethod(base.NodeToken, originalResult,
> this.staticMember, paramArray, this.typeConstraint, ref
> this.targetMethod);
> if (this.staticMember && (this.targetExpression is
> Parser.UnaryOperatorNode))
> {
> this.useCachedMethodInfo = true;
> }
> return obj3;
> }
> }
>
> Notice that if the method information has already been cached, it will
> call InvokeMethod(). Then, if we're doing a static invocation (which we
> are, in this case), the data gets cached. Next time we come through,
> because we're invoking a static method, the data's been cached, so we go
> straight to CallMethod(), which is also called by InvokeMethod(). However,
> at the bottom of InvokeMethod() is this:
>
> foreach (TypeLiteral literal in typeConstraint)
> {
> obj3 = Parser.ConvertTo(obj3, literal.Type, NodeToken);
> }
>
> I believe this is the problem...it seems like this little block of code
> really needs to be at the end of CallMethod(), not InvokeMethod(), or it
> only gets triggered the first time through for static invocations. I
> confirmed that this scenario works fine for non-static methods by simply
> doing this:
>
> ls | % { ([string]$_.LastWriteTime).GetType().FullName }
>
> And it printed out System.String for all of them. Then, I change it to
> this:
>
> ls | % {
> ([string][System.IO.File]::GetLastWriteTime($_.FullName)).GetType().FullName
> }
>
> And it printed out System.String for the first, then System.DateTime for
> the rest. Good catch!
>
> -- Ryan Milligan
>
> "Jonathan" <Jonathan@discussions.microsoft.com> wrote in message
> news:02079A14-4438-4835-9FD1-2438F493829A@microsoft.com...
>> Interesting. That works in my case as well.
>>
>> However, I am interested in an explanation of why, in my original
>> example,
>> the first iteration of the loop always converts the type no matter the
>> starting value of $i, but subsequent iterations do not.
>>
>> I'm also interested in why PowerShell's automatic type conversion isn't
>> working in this case. I'm using this code in defining an enum:
>>
>> for ($i = 0; $i -lt $args.length; $i++) {
>> [System.Int32]$Value = [Math]::Pow(2, $i)
>> $null = $EnumBuilder.DefineLiteral($args[$i], $Value)
>> }
>>
>> If I don't explicitly cast $Value to an Int, the method call to
>> DefineLiteral throws an exception "Constant does not match the defined
>> type".
>>
>> Thanks
>>
>> "Brandon Shell" wrote:
>>
>>> Worked for me if I moved the [system.int32] in front of value.
>>>
>>> Like this
>>> for ($i = 0; $i -le 5; $i++) {[System.Int32]$Value =
>>> (([Math]::Pow(2,$i)));
>>> Write-Host "$i -> $Value [$($Value.gettype().fullname)]"}
>>>
>>>
>>> "Jonathan" <Jonathan@discussions.microsoft.com> wrote in message
>>> news:6F4ED326-8217-430D-A0E7-8ED49A1D9FB1@microsoft.com...
>>> >I am having an issue with casting a double to an int32 inside a for
>>> >loop.
>>> > Executing this code:
>>> >
>>> > PS> for ($i = 0; $i -le 5; $i++) {$Value =
>>> > ([System.Int32]([Math]::Pow(2,
>>> > $i))); Write-Host "$i -> $Value [$($Value.gettype().fullname)]"}
>>> >
>>> > I get the results:
>>> >
>>> > 0 -> 1 [System.Int32]
>>> > 1 -> 2 [System.Double]
>>> > 2 -> 4 [System.Double]
>>> > 3 -> 8 [System.Double]
>>> > 4 -> 16 [System.Double]
>>> > 5 -> 32 [System.Double]
>>> >
>>> > When I execute the type conversion of the output of [Math]::Pow() at
>>> > the
>>> > PS
>>> > prompt, I get different results:
>>> >
>>> > PS> $Value = ([System.Int32]([Math]::Pow(2, 5)))
>>> > PS> Write-Host "5 -> $Value [$($Value.gettype().fullname)]"
>>> > 5 -> 32 [System.Int32]
>>> >
>>> > Is this a bug or am I missing something in my for loop?
>>> >
>>> > Thanks
>>>
>>>

>
>



My System SpecsSystem Spec
Old 04-12-2007   #7 (permalink)
Jonathan
Guest


 

Re: Typecasting issue

Ryan,

While a bit deeper than my experience level, your explanation was excellent.
Thanks for taking the time to go into such detail.

This means that for the time being, I'll have to continue with the workaround.

"Ryan Milligan" wrote:

> Oh, my...I do believe you've found a pretty serious bug in method
> invocation. Check out the code for
> System.Management.Automation.Parser+MethodCallNode.Execute() in Reflector
> (http://www.aisto.com/roeder/dotnet/), which is called when it comes time to
> execute your [Math]::Pow() method:
>
> internal override object Execute(Array input, Pipe outputPipe)
> {
> using (IDisposable disposable =
> ParseTreeNode.tracer.TraceMethod(base.NodeToken))
> {
> object[] paramArray = this.arguments.Execute(null, null) as
> object[];
> object originalResult = this.targetExpression.Execute(input, null);
> if (this.useCachedMethodInfo)
> {
> return ParserOps.CallMethod(base.NodeToken, null,
> base.NodeToken.TokenText, paramArray, this.staticMember, this.targetMethod,
> AutomationNull.Value);
> }
> object obj3 = InvokeMethod(base.NodeToken, originalResult,
> this.staticMember, paramArray, this.typeConstraint, ref this.targetMethod);
> if (this.staticMember && (this.targetExpression is
> Parser.UnaryOperatorNode))
> {
> this.useCachedMethodInfo = true;
> }
> return obj3;
> }
> }
>
> Notice that if the method information has already been cached, it will call
> InvokeMethod(). Then, if we're doing a static invocation (which we are, in
> this case), the data gets cached. Next time we come through, because we're
> invoking a static method, the data's been cached, so we go straight to
> CallMethod(), which is also called by InvokeMethod(). However, at the bottom
> of InvokeMethod() is this:
>
> foreach (TypeLiteral literal in typeConstraint)
> {
> obj3 = Parser.ConvertTo(obj3, literal.Type, NodeToken);
> }
>
> I believe this is the problem...it seems like this little block of code
> really needs to be at the end of CallMethod(), not InvokeMethod(), or it
> only gets triggered the first time through for static invocations. I
> confirmed that this scenario works fine for non-static methods by simply
> doing this:
>
> ls | % { ([string]$_.LastWriteTime).GetType().FullName }
>
> And it printed out System.String for all of them. Then, I change it to this:
>
> ls | % {
> ([string][System.IO.File]::GetLastWriteTime($_.FullName)).GetType().FullName
> }
>
> And it printed out System.String for the first, then System.DateTime for the
> rest. Good catch!
>
> -- Ryan Milligan
>
> "Jonathan" <Jonathan@discussions.microsoft.com> wrote in message
> news:02079A14-4438-4835-9FD1-2438F493829A@microsoft.com...
> > Interesting. That works in my case as well.
> >
> > However, I am interested in an explanation of why, in my original example,
> > the first iteration of the loop always converts the type no matter the
> > starting value of $i, but subsequent iterations do not.
> >
> > I'm also interested in why PowerShell's automatic type conversion isn't
> > working in this case. I'm using this code in defining an enum:
> >
> > for ($i = 0; $i -lt $args.length; $i++) {
> > [System.Int32]$Value = [Math]::Pow(2, $i)
> > $null = $EnumBuilder.DefineLiteral($args[$i], $Value)
> > }
> >
> > If I don't explicitly cast $Value to an Int, the method call to
> > DefineLiteral throws an exception "Constant does not match the defined
> > type".
> >
> > Thanks
> >
> > "Brandon Shell" wrote:
> >
> >> Worked for me if I moved the [system.int32] in front of value.
> >>
> >> Like this
> >> for ($i = 0; $i -le 5; $i++) {[System.Int32]$Value =
> >> (([Math]::Pow(2,$i)));
> >> Write-Host "$i -> $Value [$($Value.gettype().fullname)]"}
> >>
> >>
> >> "Jonathan" <Jonathan@discussions.microsoft.com> wrote in message
> >> news:6F4ED326-8217-430D-A0E7-8ED49A1D9FB1@microsoft.com...
> >> >I am having an issue with casting a double to an int32 inside a for
> >> >loop.
> >> > Executing this code:
> >> >
> >> > PS> for ($i = 0; $i -le 5; $i++) {$Value =
> >> > ([System.Int32]([Math]::Pow(2,
> >> > $i))); Write-Host "$i -> $Value [$($Value.gettype().fullname)]"}
> >> >
> >> > I get the results:
> >> >
> >> > 0 -> 1 [System.Int32]
> >> > 1 -> 2 [System.Double]
> >> > 2 -> 4 [System.Double]
> >> > 3 -> 8 [System.Double]
> >> > 4 -> 16 [System.Double]
> >> > 5 -> 32 [System.Double]
> >> >
> >> > When I execute the type conversion of the output of [Math]::Pow() at
> >> > the
> >> > PS
> >> > prompt, I get different results:
> >> >
> >> > PS> $Value = ([System.Int32]([Math]::Pow(2, 5)))
> >> > PS> Write-Host "5 -> $Value [$($Value.gettype().fullname)]"
> >> > 5 -> 32 [System.Int32]
> >> >
> >> > Is this a bug or am I missing something in my for loop?
> >> >
> >> > Thanks
> >>
> >>

>
>
>

My System SpecsSystem Spec
Closed Thread

Thread Tools
Display Modes



Similar Threads
Thread Thread Starter Forum Replies Last Post
Windows Vista mouse issue.. Possibly ease of use type issue? Malakie Vista hardware & devices 0 07-10-2008 04:30 PM
IE7 owa issue william Vista General 1 02-20-2008 04:20 AM
quirk/bug of typecasting of types in functions klumsy@gmail.com PowerShell 1 11-15-2006 07:26 PM
Monitor issue or full instal issue DaymItzJack Vista installation & setup 2 10-23-2006 07:52 PM
Routre Issue or Vista Issue Gary MCSE Vista General 1 10-15-2006 10:26 AM


Update your Vista Drivers Update Your Vista Drivers Now!!

Vistax64.com is an independent web site and has not been authorized,
sponsored, or otherwise approved by Microsoft Corporation.
"Windows Vista", the Start Orb, and related materials are trademarks of Microsoft Corp.
© Designer Media 2005-2008
Page generated in 0.38928 seconds with 10 queries