Skip to content
mnaoumov.dev
Go back

WTF Method overloads resolution in PowerShell

I have got another WTF!

It seems that PowerShell method overload resolution system is not consistent with C#

Let’s compare

C#

class Program
{
    static void Main(string[] args)
    {
        MyClass.MyMethod(false, DateTime.Now);
    }
}

public static class MyClass
{
    public static void MyMethod(object obj, DateTime dateTime)
    {
        Console.WriteLine("MyClass.MyMethod(object obj, DateTime dateTime)");
    }

    public static void MyMethod(bool b, string str)
    {
        Console.WriteLine("MyClass.MyMethod(bool b, string str)");
    }
}

vs

PowerShell

Add-Type `
@"
    using System;

    public static class MyClass
    {
        public static void MyMethod(object obj, DateTime dateTime)
        {
            Console.WriteLine("MyClass.MyMethod(object obj, DateTime dateTime)");
        }

        public static void MyMethod(bool b, string str)
        {
            Console.WriteLine("MyClass.MyMethod(bool b, string str)");
        }
    }
"@

[MyClass]::MyMethod($false, [DateTime]::Now)

C# will return

MyClass.MyMethod(object obj, DateTime dateTime)

How we expected

But PowerShell will return

MyClass.MyMethod(bool b, string str)

If we want to have the correct method called we have to be more explicit about overload we want to call

[MyClass]::MyMethod([object] $false, [DateTime]::Now)

I found this issue very annoying

I had the following NUnit-like test in PoshUnit which uses real NUnit behind the scenes

$Assert::That($false, $Is::False)

And this test failed!!!

The reason is absolutely the same

Assert.That has a lot of overloads. With my code I expected

 public static void That(object actual, IResolveConstraint expression)

but actually the following one was called

 public static void That(bool condition, string message)

It is extremely annoying.

I think it is a bug in PowerShell, not a feature

UPD:

The code above was tested in PowerShell 3

In PowerShell 2 the situation is even worse. I could not find a way to call a proper overload

Even this one does not work

[MyClass]::MyMethod([object] $false, [DateTime] ([DateTime]::Now))

UPD:

Raised a question http://stackoverflow.com/questions/13084176/powershell-method-overload-resolution-bug

UPD: Raised bug for Microsoft https://connect.microsoft.com/PowerShell/feedback/details/768901/powershell-method-overload-resolution


Share this post on:

Previous Post
PowerShell script best practices
Next Post
Indent styles holy wars