I am trying to write a comparer for my own class.
As I want everything to work in both Windows PowerShell (5.1) up till PowerShell 7, I am writing everything for Windows PowerShell first and then test PowerShell 7. Now suddenly the whole module doesn't load any more using module .\MyModule
or using the Install-Module .\MyModule
in PowerShell 7 and returns a general error:
Import-Module: Specified method is not supported.
After, removing everything that isn't related to the error, I have nailed the problem down to:
class MyClass {}
class MyComparer : Collections.Generic.IComparer[MyClass] {
[String]$PrimaryKey # Should always become first
[int] Compare ([MyClass]$Value1, [MyClass]$Value2) { return 0 }
}
Note that this (as my whole module) works fine in Windows PowerShell 5.1 and also:
[String]$PrimaryKey # Should always become first
[MyClass]
to e.g. [Object]
, like:class MyComparer : Collections.Generic.IComparer[Object] {
[String]$PrimaryKey # Should always be first
[int] Compare ([Object]$Value1, [Object]$Value2) { return 0 }
}
This is really at the edge of what I understand of (comparer) interfaces and I wonder if I am actually doing something wrong here or whether this concerns a (PowerShell 7) bug...
This is just one of the many known issues that plague PowerShell class
definitions (the meta issue tracking all class
-related issues is GitHub issue #6652):
In general, a notable limitation is that any .NET types (which PowerShell class
es too are compiled to) referenced in class
definitions (as well as param()
blocks) must have been loaded before the code in question is parsed, which precedes actual execution.
Additionally, it seems that class
es defined in the same script or module file cannot reference themselves, such as in interface implementations - see GitHub issue #10669 - or each other - as in your case, a variation of which is reported in GitHub issue #20755
It is curious that your specific code can at least be parsed in Windows PowerShell (whereas in PowerShell (Core) 7 it can only be parsed if the class
defines no properties) but the following, simpler example yields the Specified method is not supported
error in both editions:
class MyItem { }
# !! BREAKS, due to referencing [MyItem]
class MyQueue : System.Collections.Generic.Queue[MyItem] { }
The only obvious difference is that your attempt failed in the context of an interface implementation, whereas in this example it is a base-class specification.
The workaround for now is to use [object]
in lieu of MyClass
, i.e., to implement System.Collections.Generic.IComparer[object]
and to test the specific type identities at runtime.