Неявное преобразование в bool структуры, определенной в C#, не работает в PowerShell

Почему неявное преобразование в [byte] работает, а при замене byte на bool уже не работает?

т. е. следующие работы...

Add-Type -TypeDefinition @'
public readonly struct MyByte
{
    private readonly byte value;

    public MyByte( byte b ) => this.value = b;

    public static implicit operator byte( MyByte b ) => b.value;
    public static explicit operator MyByte( byte b ) => new MyByte( b );

    public override string ToString() => $"{value}";
}
'@

[byte] $d = [MyByte]::new( 1 )    # OK

... в то время как этот очень похожий код не делает:

Add-Type -TypeDefinition @'
public readonly struct MyBool
{
    private readonly bool value;

    public MyBool( bool b ) => this.value = b;

    public static implicit operator bool( MyBool b ) => b.value;
    public static explicit operator MyBool( bool b ) => new MyBool( b );

    public override string ToString() => $"{value}";
}
'@

[bool] $b = [MyBool]::new( $true )    # Error

Это приводит к следующей ошибке:

Cannot convert value "MyBool" to type "System.Boolean". Boolean parameters accept only Boolean values and numbers, such as $True, $False, 1 or 0.

Обратите внимание, что в C# неявное преобразование в bool работает как положено:

public class MyBoolTest {
    public static void Test() {
        bool b = new MyBool( true );    // OK
    }
}

Так что это похоже только на PowerShell.

(PS-версия: 7.2.2)

Странно, что $b = [bool][MyBool]::new( $true ) работает, а [bool] $b = [MyBool]::new( $true ) нет

Santiago Squarzon 26.03.2022 20:43

@SantiagoSquarzon Разница в том, что первое является явным преобразованием. Оператор неявного преобразования можно использовать в обоих случаях, но PoSh, похоже, не распознает его для неявного случая.

zett42 26.03.2022 20:49

@SantiagoSquarzon [bool][MyBool]::new( $false ) -> удивительно печатает True!

zett42 26.03.2022 21:07

@SantiagoSquarzon Как всегда, у @mklement0, похоже, ответ. Вкратце: преобразование в bool полностью обрабатывается PowerShell и игнорирует любые неявные и явные операторы приведения (подробнее см. комментарии LanguagePrimitives.cs).

zett42 26.03.2022 21:14

Кстати, $a = [MyBool]::new(1); $a | gm -force теперь $a больше не имеет значения LOL

Santiago Squarzon 26.03.2022 21:14

Это нормально, поскольку вы применяете литая нотация. См. Ограниченные переменные и Типы переменных.

JosefZ 26.03.2022 23:09

@JosefZ, ни одна из ваших ссылок не объясняет рассматриваемое поведение.

mklement0 27.03.2022 00:11
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
7
73
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

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

Вы видите два отдельных проблемных поведения PowerShell:

  • Проблемное поведение А: PowerShell имеет собственную встроенную логику преобразования в логическое значение, которая, к сожалению, нет учитывает неявные или явные операторы преобразования .NET.

    • Нижний раздел этот ответ обобщает правила этой встроенной логики, что объясняет, почему он рассматривает экземпляр Любые вашего [MyBool] типа — даже [MyBool]::new($false)$true, к сожалению.

    • Только в операциях, в которых экземпляр не приводится к логическому значению, учитываются операторы преобразования, что для большинства операторов означает использование экземпляра в ЛХС:

      [MyBool]::new($false) -eq $false # -> $true
      
      [MyBool]::new($false), 'other' -contains $false # -> $true
      
      # With -in, it is the *RHS* that matters 
      $false -in [MyBool]::new($false), 'other' # -> $true
      
    • Напротив, если вы сила логический контекст — либо с помощью логического значения в (обычно) LHS, либо с приведением скрытый к логическому — встроенная логика PowerShell — которая не учитывает операторы преобразования — срабатывает:

      $false -eq [MyBool]::new($false) # -> !! $false
      
      $false, 'other' -contains [MyBool]::new($false) # -> !! $false
      
      # With -in, it is the *RHS* that matters 
      [MyBool]::new($false) -in $false, 'other' # -> !! $false
      
      # Most insidiously, with *implicit* coercion.
      if ([MyBool]::new($false)) { 'what?' } # -> !! 'what?'
      
  • Проблемное поведение Б: Когда вы ограничение типа переменную с [bool], то есть когда вы помещаете литерал типа в слева присваиваемой переменной (например, [bool] $b = ..., в отличие от $b = [bool] (...), [1] правила связывания [bool]параметр - неожиданно и неуместно - срабатывают, которые, в отличие от встроенного преобразования любого типа в логическое, являются довольно ограничительными, как указывает сообщение об ошибке.

    • То есть только $true, $false и числа (с нулевым отображением на $false и любым ненулевым значением на $true) могут быть переданы параметру с типом [bool].

      • Обратите внимание, что сами параметры [bool] встречаются редко, потому что логическая логика PowerShell идиоматически выражается с помощью параметра [switch], который, когда ему (необычно) задается явный аргумент, является еще более строгим и принимает только $true и $false.
    • Это проблемное поведение — ненадлежащее применение логики параметр к (непараметрическому) переменные — является предметом Ошибка GitHub № 10426.


[1] The difference between the two is that type-constraining - [bool] $b = ... - effectively locks in the data type of variable $b, so that latter attempts to assign new values are coerced to the same type. By contrast, $b = [bool] (...) merely applies an ad hoc cast to force a conversion, without preventing later assignments from assigning values with different data types.

Было бы неплохо понять, почему gm также удаляет значение из экземпляра: D (мой последний комментарий к вопросу zett)

Santiago Squarzon 27.03.2022 00:09

@ Сантьяго, такое поведение действительно очень любопытно. Обратите внимание, что удаляется не ценность, а то, что форматирование для отображения внезапно перестает работать (вместо значения печатает пустую строку). Вы увидите, что значение все еще там с "$a". Я рекомендую вам либо задать новый вопрос здесь, либо создать проблему на GitHub.

mklement0 27.03.2022 00:15

Как вы думаете, это ошибка?

Santiago Squarzon 27.03.2022 00:16

@ Сантьяго: да, несомненно.

mklement0 27.03.2022 00:16

Хорошо, такое же поведение будет происходить и в классе PS со свойством hidden. И это не только gm нарушение форматирования для отображения, select * тоже

Santiago Squarzon 27.03.2022 01:11

Для интересующихся: Сантьяго опубликовал дополнительный вопрос здесь.

mklement0 27.03.2022 03:52

Отправил Ошибка GitHub № 17071, спасибо за исправление for-display formatting :) Я связал ваш комментарий, чтобы этот вопрос и ответ был виден, если вы не возражаете, пожалуйста, не удаляйте комментарий

Santiago Squarzon 27.03.2022 19:37

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