[NoBrainer] Getting constructor information with PowerShell 5 easily

Before PowerShell 5 we had to revert to reflection to be able to display constructor information in PowerShell (see Get-Constructor Fun for details). And because we used that functionality so often we created a Cmdlet Get-Constructor that is part of our biz.dfch.PS.System.Utilities module.

However with PowerShell 5 this is obsolete as it is now built into the language and runtime directly. The keyword to make this magic happen is called new (see help about_Classes or check the new class feature). Every .NET object now has an additional static method called new which is added by the PowerShell runtime to that object:

PS > [Object] | gm -static -Type Method -Name new

   TypeName: System.Object

Name MemberType Definition
---- ---------- ----------
new  Method     System.Object new()

As a side note: to verify that this method is really only added by the PowerShell runtime you can invoke [Object].GetMethods([System.Reflection.BindingFlags]::Static) and see from its (empty output) that Object does not have a new method.

This method lets you create a new object of an arbitrary type. And as with all methods in PowerShell, calling a method without its parentheses gives you all its overloads and method parameters.

So to find out about all constructors of the DatetimeOffset class you just have to invoke this:

PS > [DateTimeOffset]::new

OverloadDefinitions
-------------------
System.DateTimeOffset new(long ticks, timespan offset)
System.DateTimeOffset new(datetime dateTime)
System.DateTimeOffset new(datetime dateTime, timespan offset)
System.DateTimeOffset new(int year, int month, int day, int hour, int minute, int second, timespan offset)
System.DateTimeOffset new(int year, int month, int day, int hour, int minute, int second, int millisecond, timespan offset)
System.DateTimeOffset new(int year, int month, int day, int hour, int minute, int second, int millisecond, System.Globalization.Calendar calendar, timespan offset)

Creating an object can still be done via the New-Object Cmdlet which gives you additional PowerShell specific features of property setting and direct method invocation. However if you are interested in getting the maximum speed out of your PowerShell scripts you should use the new method as you can see from these ad hoc benchmarks:

PS > Measure-Command -Expression { 
    for($c = 0; $c -lt 1000000; $c++) 
    { 
        $dt = New-Object DateTimeOffset(2019, 04, 13, 05, 42, 08, 15, [TimeSpan]::Zero) 
    } 
};

Days              : 0
Hours             : 0
Minutes           : 2
Seconds           : 6
Milliseconds      : 619
Ticks             : 1266197990
TotalDays         : 0.00146550693287037
TotalHours        : 0.0351721663888889
TotalMinutes      : 2.11032998333333
TotalSeconds      : 126.619799
TotalMilliseconds : 126619.799

PS > Measure-Command -Expression { 
    for($c = 0; $c -lt 1000000; $c++) 
    { 
        $dt = [DateTimeOffset]::new(2019, 04, 13, 05, 42, 08, 15, [TimeSpan]::Zero) 
    } 
};

Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 2
Milliseconds      : 314
Ticks             : 23140451
TotalDays         : 2.67829293981481E-05
TotalHours        : 0.000642790305555556
TotalMinutes      : 0.0385674183333333
TotalSeconds      : 2.3140451
TotalMilliseconds : 2314.0451

The difference is roughly a factor of 50 (on my development machine)!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: