Ошибка сравнения пользовательских классов: указанный метод не поддерживается

Я пытаюсь написать компаратор для своего класса. Поскольку я хочу, чтобы все работало как в Windows PowerShell (5.1), так и в PowerShell 7, я сначала пишу все для Windows PowerShell, а затем тестирую PowerShell 7. Теперь внезапно весь модуль больше не загружается using module .\MyModule или не использую Install-Module .\MyModule в PowerShell. 7 и возвращает общую ошибку:

Import-Module: Specified method is not supported.

После удаления всего, что не связано с ошибкой, я свел проблему к следующему:

class MyClass {}

class MyComparer : Collections.Generic.IComparer[MyClass] {
    [String]$PrimaryKey # Should always become first
    [int] Compare ([MyClass]$Value1, [MyClass]$Value2) { return 0 }
}

Обратите внимание, что этот (как и весь мой модуль) отлично работает в Windows PowerShell 5.1, а также:

  • Когда я удаляю строку: [String]$PrimaryKey # Should always become first
  • или когда я меняю тип элемента с [MyClass] на, например. [Object], например:
class MyComparer : Collections.Generic.IComparer[Object] {
    [String]$PrimaryKey # Should always be first
    [int] Compare ([Object]$Value1, [Object]$Value2) { return 0 }
}

Это действительно находится на грани того, что я понимаю в интерфейсах (сравнителя), и мне интересно, действительно ли я делаю здесь что-то не так или это касается ошибки (PowerShell 7)...

Не обращайте внимания на мой предыдущий комментарий, этот вопрос другой и гораздо более интригующий 😅

Mathias R. Jessen 14.06.2024 17:44

Я пытаюсь воспроизвести — я сохранил MyModule.psm1 с содержимым вашего первого образца и go.ps1, содержащий Import-Module .\MyModule -PassThru. Если я запускаю командную строку и запускаю pwsh .\go.ps1 в этой папке, он загружает модуль и отображает результат, значит, я, должно быть, делаю что-то отличное от вашей настройки?

mclayton 14.06.2024 18:06

@mclayton, просто поместите первый пример (оба класса) в файл сценария PowerShell .ps1 и используйте для него точечный источник.

iRon 14.06.2024 18:49

похоже, вы только что нашли ошибку в pwsh 7 :) возможно, лучше поднять проблему в репозитории

Santiago Squarzon 14.06.2024 19:14

@SantiagoSquarzon, я передумал (снова) и в конце концов сообщил об ошибке в репозитории (поскольку вариант использования немного отличается от уже сообщенных проблем). См.: github.com/PowerShell/PowerShell/issues/23959

iRon 15.06.2024 13:20
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
5
90
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Это лишь одна из многих известных проблем, которые мешают определениям классов PowerShell (мета-проблема, отслеживающая все проблемы, связанные с class, — это GitHub Issue #6652):

В целом, заметным ограничением является то, что любые типы .NET (с которыми компилируются class PowerShell), на которые ссылаются определения class (а также блоки param()), должны быть загружены до анализа рассматриваемого кода, что предшествует фактическому выполнению.

Кроме того, кажется, что classes, определенные в одном и том же файле скрипта или модуля, не могут ссылаться на себя, например, в реализациях интерфейса — см. выпуск GitHub № 10669 — или друг на друга — как в вашем случае, вариант которого описан в Проблема GitHub № 20755

Любопытно, что ваш конкретный код можно, по крайней мере, проанализировать в Windows PowerShell (тогда как в PowerShell (Core) 7 его можно проанализировать только в том случае, если class не определяет никаких свойств), но следующий, более простой пример выдает ошибку Specified method is not supported в обоих случаях. издания:

class MyItem { }

# !! BREAKS, due to referencing [MyItem]
class MyQueue : System.Collections.Generic.Queue[MyItem] { }

Единственное очевидное отличие состоит в том, что ваша попытка не удалась в контексте реализации интерфейса, тогда как в этом примере это спецификация базового класса.

Обходной путь на данный момент — использовать [object] вместо MyClass, т. е. реализовать System.Collections.Generic.IComparer[object] и проверять идентификаторы конкретных типов во время выполнения.

Спасибо за пояснения и ссылки. Судя по ограничению ошибки, которое class определяет свойства, похоже, что вы также можете обойти эту проблему, выведя компаратор из дополнительного класса, который содержит соответствующие свойства: см.: мой ответ

iRon 15.06.2024 09:49

Рад слышать, что это помогло, @iRon. Ваш обходной путь изобретателен, но где-то действительно могут скрываться проблемы - см. мой комментарий к созданной вами проблеме на GitHub, #23959.

mklement0 15.06.2024 17:37

Судя по ошибке ограничения «class определяет свойства» в этой конкретной проблеме базового класса, кажется, что вы также можете обойти эту проблему, выведя компаратор из дополнительного класса «ComparerProperties», который содержит соответствующие свойства:

Прежде чем применять этот обходной путь, проверьте проблему с репо

class MyClass {
    hidden $Value
    MyClass($Value) { $this.Value = $Value }
    [String] ToString() { return $this.Value }
}

class ComparerProperties { # Prevent: Specified method is not supported
    [String[]]$PrimaryKey # Should always be first
}
    
class MyComparer : ComparerProperties, Collections.Generic.IComparer[MyClass] {
    [int] Compare ([MyClass]$MyClass1, [MyClass]$MyClass2) {
        if ($MyClass1.Value -in $this.PrimaryKey) { return -1 }
        elseif ($MyClass2.Value -in $this.PrimaryKey) { return 1 }
        elseif ($MyClass1.Value -eq $MyClass2.Value) { return 0 }
        elseif ($MyClass1.Value -lt $MyClass2.Value) { return -1 }
        else { return 1 }
    }
}
$MyList = [Collections.Generic.List[MyClass]]::New()
'b', 'id', 'c', 'a' | ForEach-Object {
    $MyList.add([MyClass]$_)
}

$Comparer = [MyComparer]::new()
$Comparer.PrimaryKey = 'id'
$MyList.Sort($Comparer)
$MyList
id
a
b
c

Или я просто ввожу парсер в заблуждение, что в итоге может мне отомстить???

Другие вопросы по теме