Windows Vista Forums

Confused getting properties of Collections of one vs. many
  1. #1


    =?Utf-8?B?TWlrZSBCcmlkZ2U=?= bridgecanada _ com> Guest

    Confused getting properties of Collections of one vs. many

    Hi-

    I am confused about the behaviour of a collection with a single element vs.
    the behaviour of a collection with multiple elements. If I have a collection
    with one element, it gives me this:

    PS> (Get-Process iexplore).Processname
    IEXPLORE
    PS>



    But querying a collection of four elements gives me an empty result:
    PS> (Get-Process svchost).Processname
    PS>

    I would expect this to either return an error, or else give me a
    four-element list. I also see that this doesn't give me an error either:

    PS> (Get-Process svchost).Xwoeifjwoeifj
    PS>

    I'm not sure what to make of that---is that what it's supposed to do?

    Thanks!

    -Mike



      My System SpecsSystem Spec

  2. #2


    George Xie [MSFT] Guest

    Re: Confused getting properties of Collections of one vs. many

    It was a designed behaviour for powershell to reduce the output of a
    collection of one object into the object itself. To force a collection to be
    returned, you can use @() operator, as below

    PS> @(get-process iexplore)[0].Processname
    IEXPLORE

    This operator will force an collection to be returned no matter whether the
    number of output data is 0, 1 or many.

    It is also a designed behavior to return null when a non-existing property
    for an object is accessed. This allows a script to operate on different kind
    of objects without having to throw a lot of errors. A lot of dynamic
    language are using similiar kind of behaviour.

    --
    George Xie [MSFT]
    Microsoft Command Shell Development
    Microsoft Corporation
    This posting is provided "AS IS" with no warranties, and confers no rights.

    "Mike Bridge bridgecanada _ com>" <mike -> wrote in message
    news:46B5B1CC-4B29-4C86-BC41-1116A399A141@microsoft.com...
    > Hi-
    >
    > I am confused about the behaviour of a collection with a single element
    > vs.
    > the behaviour of a collection with multiple elements. If I have a
    > collection
    > with one element, it gives me this:
    >
    > PS> (Get-Process iexplore).Processname
    > IEXPLORE
    > PS>
    >
    > But querying a collection of four elements gives me an empty result:
    > PS> (Get-Process svchost).Processname
    > PS>
    >
    > I would expect this to either return an error, or else give me a
    > four-element list. I also see that this doesn't give me an error either:
    >
    > PS> (Get-Process svchost).Xwoeifjwoeifj
    > PS>
    >
    > I'm not sure what to make of that---is that what it's supposed to do?
    >
    > Thanks!
    >
    > -Mike
    >
    >




      My System SpecsSystem Spec

  3. #3


    =?Utf-8?B?TWlrZSBCcmlkZ2U=?= bridgecanada _ com> Guest

    Re: Confused getting properties of Collections of one vs. many

    Hi-

    Thanks for the quick response. I assume that the philosophy behind the
    different return types is to simplify things for a programmer by guessing
    what he wants, but I wonder about the impact that this has on programming in
    PowerShell. It seems to me that it would mean that every time I write code
    which returns a collection, I will have to either test for the special case
    where the collection contains one element, or else wrap my code in that ugly
    perl-like @() operator. Personally, I think it's a Very Bad Idea to have
    different return types for the same call. Having this as the default
    violates the idea behind contract-based programming (knowing what you get
    back when you make a call) and object-oriented programming (having to test
    the type of the result when you get it back). The result is really messy and
    bug-prone code. I haven't ever seen a programming language where this
    occurs, and I doubt that anyone would expect that behaviour, especially those
    of us who are used to C#!

    As a longtime unix scripter, I'm very enthusiastic about what PowerShell
    adds to Windows (especially the object-oriented pipeline), but I hope you
    have a second look at this particular feature before the final version is
    released.

    Thanks,

    -Mike


    "George Xie [MSFT]" wrote:

    > It was a designed behaviour for powershell to reduce the output of a
    > collection of one object into the object itself. To force a collection to be
    > returned, you can use @() operator, as below
    >
    > PS> @(get-process iexplore)[0].Processname
    > IEXPLORE
    >
    > This operator will force an collection to be returned no matter whether the
    > number of output data is 0, 1 or many.
    >
    > It is also a designed behavior to return null when a non-existing property
    > for an object is accessed. This allows a script to operate on different kind
    > of objects without having to throw a lot of errors. A lot of dynamic
    > language are using similiar kind of behaviour.
    >
    > --
    > George Xie [MSFT]
    > Microsoft Command Shell Development
    > Microsoft Corporation
    > This posting is provided "AS IS" with no warranties, and confers no rights.
    >
    > "Mike Bridge bridgecanada _ com>" <mike -> wrote in message
    > news:46B5B1CC-4B29-4C86-BC41-1116A399A141@microsoft.com...
    > > Hi-
    > >
    > > I am confused about the behaviour of a collection with a single element
    > > vs.
    > > the behaviour of a collection with multiple elements. If I have a
    > > collection
    > > with one element, it gives me this:
    > >
    > > PS> (Get-Process iexplore).Processname
    > > IEXPLORE
    > > PS>
    > >
    > > But querying a collection of four elements gives me an empty result:
    > > PS> (Get-Process svchost).Processname
    > > PS>
    > >
    > > I would expect this to either return an error, or else give me a
    > > four-element list. I also see that this doesn't give me an error either:
    > >
    > > PS> (Get-Process svchost).Xwoeifjwoeifj
    > > PS>
    > >
    > > I'm not sure what to make of that---is that what it's supposed to do?
    > >
    > > Thanks!
    > >
    > > -Mike
    > >
    > >

    >
    >
    >


      My System SpecsSystem Spec

  4. #4


    =?Utf-8?B?TWlrZSBCcmlkZ2U=?= bridgecanada _ com> Guest

    Re: Confused getting properties of Collections of one vs. many

    Hi-

    I had a closer look at this, and it's more confusing than I thought:

    PS> $a = @(1,2,3)
    PS> $b = @(3,4,5)
    PS> $c = @($a,$b)
    PS> $c.length
    2

    ....but

    PS> $d = @(1,2,3)
    PS> $e = @($d)
    PS> $e.length
    3

    It seems to me that due to the one-vs-many guesswork that's going on behind
    the scenes, you *can't* be sure that you're creating an array of arrays
    unless you wrap both these in the @() operator, i.e.:

    $c = @(@($a),@($b))

    Ugh!!

    -Mike




    But passing


    "George Xie [MSFT]" wrote:

    > It was a designed behaviour for powershell to reduce the output of a
    > collection of one object into the object itself. To force a collection to be
    > returned, you can use @() operator, as below
    >
    > PS> @(get-process iexplore)[0].Processname
    > IEXPLORE
    >
    > This operator will force an collection to be returned no matter whether the
    > number of output data is 0, 1 or many.
    >
    > It is also a designed behavior to return null when a non-existing property
    > for an object is accessed. This allows a script to operate on different kind
    > of objects without having to throw a lot of errors. A lot of dynamic
    > language are using similiar kind of behaviour.
    >
    > --
    > George Xie [MSFT]
    > Microsoft Command Shell Development
    > Microsoft Corporation
    > This posting is provided "AS IS" with no warranties, and confers no rights.
    >
    > "Mike Bridge bridgecanada _ com>" <mike -> wrote in message
    > news:46B5B1CC-4B29-4C86-BC41-1116A399A141@microsoft.com...
    > > Hi-
    > >
    > > I am confused about the behaviour of a collection with a single element
    > > vs.
    > > the behaviour of a collection with multiple elements. If I have a
    > > collection
    > > with one element, it gives me this:
    > >
    > > PS> (Get-Process iexplore).Processname
    > > IEXPLORE
    > > PS>
    > >
    > > But querying a collection of four elements gives me an empty result:
    > > PS> (Get-Process svchost).Processname
    > > PS>
    > >
    > > I would expect this to either return an error, or else give me a
    > > four-element list. I also see that this doesn't give me an error either:
    > >
    > > PS> (Get-Process svchost).Xwoeifjwoeifj
    > > PS>
    > >
    > > I'm not sure what to make of that---is that what it's supposed to do?
    > >
    > > Thanks!
    > >
    > > -Mike
    > >
    > >

    >
    >
    >


      My System SpecsSystem Spec

  5. #5


    =?Utf-8?B?TWlrZSBCcmlkZ2U=?= bridgecanada _ com> Guest

    Re: Confused getting properties of Collections of one vs. many

    Hi-

    Hmm.... maybe I can't even be sure of that. I was trying to take an array
    and add it as the first element of another array, but I can't figure out how
    to do it.

    The first $j.length call returns what I expect, but it seems that the second
    should return a length of 1:

    PS> $i = @(1,2,3)
    PS> $j = @($i)
    PS> $j.length
    3
    PS> $j = @(@($i))
    PS> $j.length
    3

    Is there a way to force $i to be added to $j as an array, instead of
    appending each of $i's elements individually

    Thanks,

    -Mike



    "Mike Bridge" wrote:

    > Hi-
    >
    > I had a closer look at this, and it's more confusing than I thought:
    >
    > PS> $a = @(1,2,3)
    > PS> $b = @(3,4,5)
    > PS> $c = @($a,$b)
    > PS> $c.length
    > 2
    >
    > ...but
    >
    > PS> $d = @(1,2,3)
    > PS> $e = @($d)
    > PS> $e.length
    > 3
    >
    > It seems to me that due to the one-vs-many guesswork that's going on behind
    > the scenes, you *can't* be sure that you're creating an array of arrays
    > unless you wrap both these in the @() operator, i.e.:
    >
    > $c = @(@($a),@($b))
    >
    > Ugh!!
    >
    > -Mike
    >
    >
    >
    >
    > But passing
    >
    >
    > "George Xie [MSFT]" wrote:
    >
    > > It was a designed behaviour for powershell to reduce the output of a
    > > collection of one object into the object itself. To force a collection to be
    > > returned, you can use @() operator, as below
    > >
    > > PS> @(get-process iexplore)[0].Processname
    > > IEXPLORE
    > >
    > > This operator will force an collection to be returned no matter whether the
    > > number of output data is 0, 1 or many.
    > >
    > > It is also a designed behavior to return null when a non-existing property
    > > for an object is accessed. This allows a script to operate on different kind
    > > of objects without having to throw a lot of errors. A lot of dynamic
    > > language are using similiar kind of behaviour.
    > >
    > > --
    > > George Xie [MSFT]
    > > Microsoft Command Shell Development
    > > Microsoft Corporation
    > > This posting is provided "AS IS" with no warranties, and confers no rights.
    > >
    > > "Mike Bridge bridgecanada _ com>" <mike -> wrote in message
    > > news:46B5B1CC-4B29-4C86-BC41-1116A399A141@microsoft.com...
    > > > Hi-
    > > >
    > > > I am confused about the behaviour of a collection with a single element
    > > > vs.
    > > > the behaviour of a collection with multiple elements. If I have a
    > > > collection
    > > > with one element, it gives me this:
    > > >
    > > > PS> (Get-Process iexplore).Processname
    > > > IEXPLORE
    > > > PS>
    > > >
    > > > But querying a collection of four elements gives me an empty result:
    > > > PS> (Get-Process svchost).Processname
    > > > PS>
    > > >
    > > > I would expect this to either return an error, or else give me a
    > > > four-element list. I also see that this doesn't give me an error either:
    > > >
    > > > PS> (Get-Process svchost).Xwoeifjwoeifj
    > > > PS>
    > > >
    > > > I'm not sure what to make of that---is that what it's supposed to do?
    > > >
    > > > Thanks!
    > > >
    > > > -Mike
    > > >
    > > >

    > >
    > >
    > >


      My System SpecsSystem Spec

  6. #6


    xshell Guest

    Re: Confused getting properties of Collections of one vs. many

    Or you can just use the comma operator

    40[~]> $a=1,2,3
    41[~]> $a.gettype().Name
    Object[]
    42[~]> $b=3,4,5
    43[~]> $c=,$a,$b
    44[~]> $c.gettype().Name
    Object[]
    45[~]> $c.Length
    2
    46[~]> $c[0]
    1
    2
    3
    47[~]> $c[1]
    3
    4
    5
    48[~]>

    "Mike Bridge bridgecanada _ com>" <mike -> wrote in message
    news:FCA39337-0BC7-4924-9544-5FF9966611B4@microsoft.com...
    > Hi-
    >
    > I had a closer look at this, and it's more confusing than I thought:
    >
    > PS> $a = @(1,2,3)
    > PS> $b = @(3,4,5)
    > PS> $c = @($a,$b)
    > PS> $c.length
    > 2
    >
    > ...but
    >
    > PS> $d = @(1,2,3)
    > PS> $e = @($d)
    > PS> $e.length
    > 3
    >
    > It seems to me that due to the one-vs-many guesswork that's going on
    > behind
    > the scenes, you *can't* be sure that you're creating an array of arrays
    > unless you wrap both these in the @() operator, i.e.:
    >
    > $c = @(@($a),@($b))
    >
    > Ugh!!
    >
    > -Mike
    >
    >
    >
    >
    > But passing
    >
    >
    > "George Xie [MSFT]" wrote:
    >
    >> It was a designed behaviour for powershell to reduce the output of a
    >> collection of one object into the object itself. To force a collection to
    >> be
    >> returned, you can use @() operator, as below
    >>
    >> PS> @(get-process iexplore)[0].Processname
    >> IEXPLORE
    >>
    >> This operator will force an collection to be returned no matter whether
    >> the
    >> number of output data is 0, 1 or many.
    >>
    >> It is also a designed behavior to return null when a non-existing
    >> property
    >> for an object is accessed. This allows a script to operate on different
    >> kind
    >> of objects without having to throw a lot of errors. A lot of dynamic
    >> language are using similiar kind of behaviour.
    >>
    >> --
    >> George Xie [MSFT]
    >> Microsoft Command Shell Development
    >> Microsoft Corporation
    >> This posting is provided "AS IS" with no warranties, and confers no
    >> rights.
    >>
    >> "Mike Bridge bridgecanada _ com>" <mike -> wrote in message
    >> news:46B5B1CC-4B29-4C86-BC41-1116A399A141@microsoft.com...
    >> > Hi-
    >> >
    >> > I am confused about the behaviour of a collection with a single element
    >> > vs.
    >> > the behaviour of a collection with multiple elements. If I have a
    >> > collection
    >> > with one element, it gives me this:
    >> >
    >> > PS> (Get-Process iexplore).Processname
    >> > IEXPLORE
    >> > PS>
    >> >
    >> > But querying a collection of four elements gives me an empty result:
    >> > PS> (Get-Process svchost).Processname
    >> > PS>
    >> >
    >> > I would expect this to either return an error, or else give me a
    >> > four-element list. I also see that this doesn't give me an error
    >> > either:
    >> >
    >> > PS> (Get-Process svchost).Xwoeifjwoeifj
    >> > PS>
    >> >
    >> > I'm not sure what to make of that---is that what it's supposed to do?
    >> >
    >> > Thanks!
    >> >
    >> > -Mike
    >> >
    >> >

    >>
    >>
    >>




      My System SpecsSystem Spec

  7. #7


    xshell Guest

    Re: Confused getting properties of Collections of one vs. many

    48[~]> $i=1,2,3
    49[~]> $j=,$i
    50[~]> $j.Length
    1
    51[~]>
    "Mike Bridge bridgecanada _ com>" <mike -> wrote in message
    news:EA9579EF-883D-46D6-97DB-427C6C2B79C2@microsoft.com...
    > Hi-
    >
    > Hmm.... maybe I can't even be sure of that. I was trying to take an array
    > and add it as the first element of another array, but I can't figure out
    > how
    > to do it.
    >
    > The first $j.length call returns what I expect, but it seems that the
    > second
    > should return a length of 1:
    >
    > PS> $i = @(1,2,3)
    > PS> $j = @($i)
    > PS> $j.length
    > 3
    > PS> $j = @(@($i))
    > PS> $j.length
    > 3
    >
    > Is there a way to force $i to be added to $j as an array, instead of
    > appending each of $i's elements individually
    >
    > Thanks,
    >
    > -Mike
    >
    >
    >
    > "Mike Bridge" wrote:
    >
    >> Hi-
    >>
    >> I had a closer look at this, and it's more confusing than I thought:
    >>
    >> PS> $a = @(1,2,3)
    >> PS> $b = @(3,4,5)
    >> PS> $c = @($a,$b)
    >> PS> $c.length
    >> 2
    >>
    >> ...but
    >>
    >> PS> $d = @(1,2,3)
    >> PS> $e = @($d)
    >> PS> $e.length
    >> 3
    >>
    >> It seems to me that due to the one-vs-many guesswork that's going on
    >> behind
    >> the scenes, you *can't* be sure that you're creating an array of arrays
    >> unless you wrap both these in the @() operator, i.e.:
    >>
    >> $c = @(@($a),@($b))
    >>
    >> Ugh!!
    >>
    >> -Mike
    >>
    >>
    >>
    >>
    >> But passing
    >>
    >>
    >> "George Xie [MSFT]" wrote:
    >>
    >> > It was a designed behaviour for powershell to reduce the output of a
    >> > collection of one object into the object itself. To force a collection
    >> > to be
    >> > returned, you can use @() operator, as below
    >> >
    >> > PS> @(get-process iexplore)[0].Processname
    >> > IEXPLORE
    >> >
    >> > This operator will force an collection to be returned no matter whether
    >> > the
    >> > number of output data is 0, 1 or many.
    >> >
    >> > It is also a designed behavior to return null when a non-existing
    >> > property
    >> > for an object is accessed. This allows a script to operate on different
    >> > kind
    >> > of objects without having to throw a lot of errors. A lot of dynamic
    >> > language are using similiar kind of behaviour.
    >> >
    >> > --
    >> > George Xie [MSFT]
    >> > Microsoft Command Shell Development
    >> > Microsoft Corporation
    >> > This posting is provided "AS IS" with no warranties, and confers no
    >> > rights.
    >> >
    >> > "Mike Bridge bridgecanada _ com>" <mike -> wrote in message
    >> > news:46B5B1CC-4B29-4C86-BC41-1116A399A141@microsoft.com...
    >> > > Hi-
    >> > >
    >> > > I am confused about the behaviour of a collection with a single
    >> > > element
    >> > > vs.
    >> > > the behaviour of a collection with multiple elements. If I have a
    >> > > collection
    >> > > with one element, it gives me this:
    >> > >
    >> > > PS> (Get-Process iexplore).Processname
    >> > > IEXPLORE
    >> > > PS>
    >> > >
    >> > > But querying a collection of four elements gives me an empty result:
    >> > > PS> (Get-Process svchost).Processname
    >> > > PS>
    >> > >
    >> > > I would expect this to either return an error, or else give me a
    >> > > four-element list. I also see that this doesn't give me an error
    >> > > either:
    >> > >
    >> > > PS> (Get-Process svchost).Xwoeifjwoeifj
    >> > > PS>
    >> > >
    >> > > I'm not sure what to make of that---is that what it's supposed to do?
    >> > >
    >> > > Thanks!
    >> > >
    >> > > -Mike
    >> > >
    >> > >
    >> >
    >> >
    >> >




      My System SpecsSystem Spec

  8. #8


    =?Utf-8?B?TWlrZSBCcmlkZ2U=?= bridgecanada _ com> Guest

    Re: Confused getting properties of Collections of one vs. many

    Hi-

    Sorry if I'm being thickheaded here, but I still don't see how I can
    generalize this to my original problem. If I apply this to the first post in
    this thread, I get this:

    PS> $a=,(get-process iexplore) #one element
    PS> $a=,(get-process svchost) #many elements
    PS > $a[0].gettype() | format-list BaseType

    BaseType : System.ComponentModel.Component

    PS > $b[0].gettype() | format-list BaseType

    BaseType : System.Array

    It appears to be impossible in the PowerShell to determine the return type
    (object vs. array) in advance without testing every single result in every
    call. As far as I can tell, I can't use any collection-based commands in a
    pipeline, because I can't show in advance what each command will return!

    I'm a big fan of the stuff you guys doing, but unless you can show me
    otherwise, I can't help but think that this is a significant defect in the
    PowerShell language definition, and a violation of both the object-oriented
    programming paradigm and the contract-programming paradigm.

    Thanks,

    -Mike



    "xshell" wrote:

    > Or you can just use the comma operator
    >
    > 40[~]> $a=1,2,3
    > 41[~]> $a.gettype().Name
    > Object[]
    > 42[~]> $b=3,4,5
    > 43[~]> $c=,$a,$b
    > 44[~]> $c.gettype().Name
    > Object[]
    > 45[~]> $c.Length
    > 2
    > 46[~]> $c[0]
    > 1
    > 2
    > 3
    > 47[~]> $c[1]
    > 3
    > 4
    > 5
    > 48[~]>
    >
    > "Mike Bridge bridgecanada _ com>" <mike -> wrote in message
    > news:FCA39337-0BC7-4924-9544-5FF9966611B4@microsoft.com...
    > > Hi-
    > >
    > > I had a closer look at this, and it's more confusing than I thought:
    > >
    > > PS> $a = @(1,2,3)
    > > PS> $b = @(3,4,5)
    > > PS> $c = @($a,$b)
    > > PS> $c.length
    > > 2
    > >
    > > ...but
    > >
    > > PS> $d = @(1,2,3)
    > > PS> $e = @($d)
    > > PS> $e.length
    > > 3
    > >
    > > It seems to me that due to the one-vs-many guesswork that's going on
    > > behind
    > > the scenes, you *can't* be sure that you're creating an array of arrays
    > > unless you wrap both these in the @() operator, i.e.:
    > >
    > > $c = @(@($a),@($b))
    > >
    > > Ugh!!
    > >
    > > -Mike
    > >
    > >
    > >
    > >
    > > But passing
    > >
    > >
    > > "George Xie [MSFT]" wrote:
    > >
    > >> It was a designed behaviour for powershell to reduce the output of a
    > >> collection of one object into the object itself. To force a collection to
    > >> be
    > >> returned, you can use @() operator, as below
    > >>
    > >> PS> @(get-process iexplore)[0].Processname
    > >> IEXPLORE
    > >>
    > >> This operator will force an collection to be returned no matter whether
    > >> the
    > >> number of output data is 0, 1 or many.
    > >>
    > >> It is also a designed behavior to return null when a non-existing
    > >> property
    > >> for an object is accessed. This allows a script to operate on different
    > >> kind
    > >> of objects without having to throw a lot of errors. A lot of dynamic
    > >> language are using similiar kind of behaviour.
    > >>
    > >> --
    > >> George Xie [MSFT]
    > >> Microsoft Command Shell Development
    > >> Microsoft Corporation
    > >> This posting is provided "AS IS" with no warranties, and confers no
    > >> rights.
    > >>
    > >> "Mike Bridge bridgecanada _ com>" <mike -> wrote in message
    > >> news:46B5B1CC-4B29-4C86-BC41-1116A399A141@microsoft.com...
    > >> > Hi-
    > >> >
    > >> > I am confused about the behaviour of a collection with a single element
    > >> > vs.
    > >> > the behaviour of a collection with multiple elements. If I have a
    > >> > collection
    > >> > with one element, it gives me this:
    > >> >
    > >> > PS> (Get-Process iexplore).Processname
    > >> > IEXPLORE
    > >> > PS>
    > >> >
    > >> > But querying a collection of four elements gives me an empty result:
    > >> > PS> (Get-Process svchost).Processname
    > >> > PS>
    > >> >
    > >> > I would expect this to either return an error, or else give me a
    > >> > four-element list. I also see that this doesn't give me an error
    > >> > either:
    > >> >
    > >> > PS> (Get-Process svchost).Xwoeifjwoeifj
    > >> > PS>
    > >> >
    > >> > I'm not sure what to make of that---is that what it's supposed to do?
    > >> >
    > >> > Thanks!
    > >> >
    > >> > -Mike
    > >> >
    > >> >
    > >>
    > >>
    > >>

    >
    >
    >


      My System SpecsSystem Spec

  9. #9


    Jouko Kynsijärvi Guest

    Re: Confused getting properties of Collections of one vs. many

    > Sorry if I'm being thickheaded here, but I still don't see how I can
    > generalize this to my original problem. If I apply this to the first
    > post in this thread, I get this:
    >
    >> $a=,(get-process iexplore) #one element
    >> $a=,(get-process svchost) #many elements

    > PS > $a[0].gettype() | format-list BaseType
    >
    > BaseType : System.ComponentModel.Component
    >
    > PS > $b[0].gettype() | format-list BaseType
    >
    > BaseType : System.Array
    >
    > It appears to be impossible in the PowerShell to determine the return
    > type (object vs. array) in advance without testing every single
    > result in every call. As far as I can tell, I can't use any
    > collection-based commands in a pipeline, because I can't show in
    > advance what each command will return!


    If you always want to get back an array, even when a single value or $null
    is returned, use @():

    [~] $a = @(get-process xxxxx*) # zero
    [~] $b = @(get-process csrss) # one
    [~] $c = @(get-process svchost) # many
    [~] $a.gettype().fullname
    [~] $b.gettype().fullname
    [~] $c.gettype().fullname
    System.Object[]
    System.Object[]
    System.Object[]

    If you always want to get back a single value, even when multiple values are
    returned, use this:

    [~] $d = (get-process svchost | select -first 1)
    [~] $d.gettype().fullname
    System.Diagnostics.Process
    ($d would be $null if get-process returned zero values)



      My System SpecsSystem Spec

  10. #10


    George Xie [MSFT] Guest

    Re: Confused getting properties of Collections of one vs. many

    I agree that there can be a lot of confusion about this behaviour around
    return type from a command. As I mentioned before, we reduce the collection
    of one object to the object itself. This is one of the controversial
    desisions we made. To resolve this dilemma as you mentioned below, @()
    operator is introduced so that this reduction is not performed.

    The best way to think of @() operator is to treat it as a conversion
    operator. If it is applied to an collection, it will return that collection
    itself. If it is applied to an object that is not a collection, it will wrap
    it in an collection. What this means is that, (1,2,3), @(1,2,3),
    @(@(1,2,3)), ..., will all result in the same array of 1,2,3. On the other
    hand, @(1), will be an array including 1.

    Comma (,) operator, on the other hand, is an array wrapping operator. An new
    array is always created from this operator. As a result, ,1 is an array of
    1. ,,1 is an array of array of 1, and so on.

    --
    George Xie [MSFT]
    Microsoft Command Shell Development
    Microsoft Corporation
    This posting is provided "AS IS" with no warranties, and confers no rights.

    "Mike Bridge bridgecanada _ com>" <mike -> wrote in message
    news:376FEFF1-986D-419E-8596-70C412E692A2@microsoft.com...
    > Hi-
    >
    > Sorry if I'm being thickheaded here, but I still don't see how I can
    > generalize this to my original problem. If I apply this to the first post
    > in
    > this thread, I get this:
    >
    > PS> $a=,(get-process iexplore) #one element
    > PS> $a=,(get-process svchost) #many elements
    > PS > $a[0].gettype() | format-list BaseType
    >
    > BaseType : System.ComponentModel.Component
    >
    > PS > $b[0].gettype() | format-list BaseType
    >
    > BaseType : System.Array
    >
    > It appears to be impossible in the PowerShell to determine the return type
    > (object vs. array) in advance without testing every single result in every
    > call. As far as I can tell, I can't use any collection-based commands in
    > a
    > pipeline, because I can't show in advance what each command will return!
    >
    > I'm a big fan of the stuff you guys doing, but unless you can show me
    > otherwise, I can't help but think that this is a significant defect in the
    > PowerShell language definition, and a violation of both the
    > object-oriented
    > programming paradigm and the contract-programming paradigm.
    >
    > Thanks,
    >
    > -Mike
    >
    >
    >
    > "xshell" wrote:
    >
    >> Or you can just use the comma operator
    >>
    >> 40[~]> $a=1,2,3
    >> 41[~]> $a.gettype().Name
    >> Object[]
    >> 42[~]> $b=3,4,5
    >> 43[~]> $c=,$a,$b
    >> 44[~]> $c.gettype().Name
    >> Object[]
    >> 45[~]> $c.Length
    >> 2
    >> 46[~]> $c[0]
    >> 1
    >> 2
    >> 3
    >> 47[~]> $c[1]
    >> 3
    >> 4
    >> 5
    >> 48[~]>
    >>
    >> "Mike Bridge bridgecanada _ com>" <mike -> wrote in message
    >> news:FCA39337-0BC7-4924-9544-5FF9966611B4@microsoft.com...
    >> > Hi-
    >> >
    >> > I had a closer look at this, and it's more confusing than I thought:
    >> >
    >> > PS> $a = @(1,2,3)
    >> > PS> $b = @(3,4,5)
    >> > PS> $c = @($a,$b)
    >> > PS> $c.length
    >> > 2
    >> >
    >> > ...but
    >> >
    >> > PS> $d = @(1,2,3)
    >> > PS> $e = @($d)
    >> > PS> $e.length
    >> > 3
    >> >
    >> > It seems to me that due to the one-vs-many guesswork that's going on
    >> > behind
    >> > the scenes, you *can't* be sure that you're creating an array of arrays
    >> > unless you wrap both these in the @() operator, i.e.:
    >> >
    >> > $c = @(@($a),@($b))
    >> >
    >> > Ugh!!
    >> >
    >> > -Mike
    >> >
    >> >
    >> >
    >> >
    >> > But passing
    >> >
    >> >
    >> > "George Xie [MSFT]" wrote:
    >> >
    >> >> It was a designed behaviour for powershell to reduce the output of a
    >> >> collection of one object into the object itself. To force a collection
    >> >> to
    >> >> be
    >> >> returned, you can use @() operator, as below
    >> >>
    >> >> PS> @(get-process iexplore)[0].Processname
    >> >> IEXPLORE
    >> >>
    >> >> This operator will force an collection to be returned no matter
    >> >> whether
    >> >> the
    >> >> number of output data is 0, 1 or many.
    >> >>
    >> >> It is also a designed behavior to return null when a non-existing
    >> >> property
    >> >> for an object is accessed. This allows a script to operate on
    >> >> different
    >> >> kind
    >> >> of objects without having to throw a lot of errors. A lot of dynamic
    >> >> language are using similiar kind of behaviour.
    >> >>
    >> >> --
    >> >> George Xie [MSFT]
    >> >> Microsoft Command Shell Development
    >> >> Microsoft Corporation
    >> >> This posting is provided "AS IS" with no warranties, and confers no
    >> >> rights.
    >> >>
    >> >> "Mike Bridge bridgecanada _ com>" <mike -> wrote in message
    >> >> news:46B5B1CC-4B29-4C86-BC41-1116A399A141@microsoft.com...
    >> >> > Hi-
    >> >> >
    >> >> > I am confused about the behaviour of a collection with a single
    >> >> > element
    >> >> > vs.
    >> >> > the behaviour of a collection with multiple elements. If I have a
    >> >> > collection
    >> >> > with one element, it gives me this:
    >> >> >
    >> >> > PS> (Get-Process iexplore).Processname
    >> >> > IEXPLORE
    >> >> > PS>
    >> >> >
    >> >> > But querying a collection of four elements gives me an empty result:
    >> >> > PS> (Get-Process svchost).Processname
    >> >> > PS>
    >> >> >
    >> >> > I would expect this to either return an error, or else give me a
    >> >> > four-element list. I also see that this doesn't give me an error
    >> >> > either:
    >> >> >
    >> >> > PS> (Get-Process svchost).Xwoeifjwoeifj
    >> >> > PS>
    >> >> >
    >> >> > I'm not sure what to make of that---is that what it's supposed to
    >> >> > do?
    >> >> >
    >> >> > Thanks!
    >> >> >
    >> >> > -Mike
    >> >> >
    >> >> >
    >> >>
    >> >>
    >> >>

    >>
    >>
    >>




      My System SpecsSystem Spec

Page 1 of 2 12 LastLast
Confused getting properties of Collections of one vs. many problems?

Similar Threads
Thread Thread Starter Forum Replies Last Post
Icon libraries or collections MikeB Vista General 4 12 Jan 2009
System.Collections.Generic.List<int> myList = new System.Collections.Generic.List<int>(100); DR .NET General 1 09 Apr 2008
Generics and collections Martin Robins .NET General 8 05 Apr 2008
Type formatting question on properties that are collections Keith Hill [MVP] PowerShell 7 01 Jan 2007
How to serialize the Generic collections in WCF =?Utf-8?B?UmFtYXJhanU=?= Indigo 1 26 Jul 2006