Powershell: Get-Member should show extension methods

Created on 7 Feb 2020  路  16Comments  路  Source: PowerShell/PowerShell

Summary of the new feature/enhancement

PowerShell engine adds .Where and .ForEach extension methods to IEnumerable collections. There is code to support tab completion, but when a user inspects an object via Get-Member, they don't show up.

Proposed technical implementation details (optional)

Since we know these extension methods are available on IEnumerable collections, we should just expose them via Get-Member and call the MemberType ExtensionMethod. Formatting would need to increase the column width by 1 to accommodate.

Also return the overload definitions like other methods:

PS> @(1).GetType

OverloadDefinitions
-------------------
type GetType()

PS> @(1).ForEach
PS>
Area-Cmdlets-Utility Issue-Enhancement

Most helpful comment

Because these automatic members (hint, hint) have nothing to do with LINQ (note that @SeeminglyScience said LINQ-_esque_, i.e., LINQ-_like_)

All 16 comments

Since we know these extension methods are available on IEnumerable collections

Actually, they're (sensibly) available on _any_ object and even on $null - in the interest of unified treatment of scalars and collections:

PS> (1).foreach({ $_ + 1 })
2
# Produces no output, because there's nothing to enumerate,
# but the fact that invoking the method doesn't produce an exception is evidence
# that the method is supported
PS> $null.foreach({ 'move along, nothing to see here' })

Tab completion indeed currently seems limited to IEnumerables.

Also, calling them _extension methods_ invites confusion with actual .NET extension methods (which aren't supported at all in PowerShell at this point).

Also, calling them extension methods invites confusion with actual .NET extension methods (which aren't supported at all in PowerShell at this point).

Yeah. Probably a good idea to not conflate the terms there. They're ETS methods, aren't they?

Should we generalize this for all ETS methods?

Yeah. Probably a good idea to not conflate the terms there. They're ETS methods, aren't they?

ETS members are also a different thing. These are currently most commonly referred to as "magic" methods, they exist mostly in the InvokeMember binder itself. They... could use a better name though probably.

IntrinsicMethod maybe? Or does that imply that it's intrinsic to the object rather than to PowerShell? I guess extrinsic would make more sense but that word probably isn't used often enough to be useful.

Thanks for confirming the hard-wired nature of these members, @SeeminglyScience.

True ETS methods - those associated with specific types - do already show in Get-Member's output, and you can ask for them in isolation with Get-Member -View Extended:

PS> [xml]::new() | Get-Member -View Extended

   TypeName: System.Xml.XmlDocument

Name     MemberType Definition
----     ---------- ----------
ToString CodeMethod static string XmlNode(psobject instance)

As an aside: The "magic" members .ForEach(), .Where(), .Count and .Length, as well as the indexer you can apply to any object as well as to $null, in addition to being hard-wired, regrettably do not even _behave_ like ETS members, at least not always, which has the very unfortunate manifestation that you cannot invoke .Count on an object while Set-StrictMode -Version 2 or higher is in effect - see #2798 (note that the "magic" indexer still works in that scenario).

Perhaps we can come up with a new -View enumeration value to show the magic, if you will, which also forces us to come up with a better name.

  • -View Engine?
  • -View BuiltIn?
  • -View PanTypical, -View Monad? (jk)

Showing them in Get-Member's _default_ output may be too distracting, however , so we could restrict them to -Force and -View All use (in addition to the "magic"-specific view).

it's intrinsic to the object rather than to PowerShell?

Yes, I think that's a problematic ambiguity; also, we want to talk about _members_ in general, not just methods.

"extrinsic" is probably too arcane, yes.

I guess "engine(-supplied) member" would tell us that these are members are provided by PowerShell itself - or is "engine" itself too general a word?

If I was not very familiar with PowerShell and I saw a member marked as "engine" I think I would assume I'm not supposed to use it.

Why do we need special view for the ForEach() and Where() methods? We could add them to Extended view.

First, my vote is not to limit the display to these two methods, but to also show that .Count,.Length and indexing are available - show _all_ the magic, at least on demand.

Get-Member currently includes ETS members _by default_ in its output.

If we treat magic members like ETS members, they will also show up _by default_.

Do we want that? I personally think it would be too distracting, because the magic isn't _type-specific_.

I suppose we could show them only with Get-Member -View Extended, but that would be a somewhat obscure distinction, given that "The default is Adapted, Extended." Why would -View Extended _alone_ then show additional members?

Independently, I still think we should come up with a descriptive name for the magic, even if only for the sake of _documenting_ them.

Do we want that? I personally think it would be too distracting, because the magic isn't _type-specific_.

Agreed. Also because it kind of limits how many can be made. I think there's a lot of room for some more LINQ-esque magic methods, and if they're all shown by default that'll be a lot of noise.

I suppose we could show them only with Get-Member -View Extended, but that would be a somewhat obscure distinction, given that "The default is Adapted, Extended." Why would -View Extended _alone_ then show additional members?

Ah I didn't realize that. Yeah that doesn't make sense then.

Independently, I still think we should come up with a descriptive name for the magic, even if only for the sake of _documenting_ them.

馃憤

Re terminology:

As an aside: I just noticed that the Get-Member topic uses "intrinsic" to refer to the type-native properties. (in fact, the term does refer to _engine_-supplied members such as .psobject; in that sense they are intrinsic to helper type [psobject]; still, the name is ambiguous).

It occurred to me that there is a well-established term that could fit: _automatic_, as used in the name for the built-in variables.

So how about "automatic [type] members" and -View Automatic?

If LINQ was mentioned why do not use the name?

Because these automatic members (hint, hint) have nothing to do with LINQ (note that @SeeminglyScience said LINQ-_esque_, i.e., LINQ-_like_)

Please see https://github.com/MicrosoftDocs/PowerShell-Docs/issues/5627 for a proposal to establish an official term for these automatic members and to document in them in a dedicated conceptual topic.

I noticed that _some_ of the automatic members - namely the reflection-related ones (.psobject, .pstyenames, ...) - already _do_ show up with -Force, so showing them _all_ with -Force makes sense, complemented by a dedicated -View Automatic.

Was this page helpful?
0 / 5 - 0 ratings