Форум программистов, компьютерный форум, киберфорум
PowerShell
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 5.00/7: Рейтинг темы: голосов - 7, средняя оценка - 5.00
Модератор
 Аватар для Curry
5154 / 3474 / 536
Регистрация: 01.06.2013
Сообщений: 7,532
Записей в блоге: 9

Непонятка с enum+switch

17.12.2024, 14:58. Показов 2474. Ответов 29

Студворк — интернет-сервис помощи студентам
Привет всем!

Решил сделать разные действия по нажатию клавиш ($host.UI.RawUI.ReadKey), однако
PowerShell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
enum VirtualKeyCode {
    D = 0x44
    Q = 0x51    
    S = 0x53 
}
 
$key = 0x51
 
[VirtualKeyCode]::Q -eq $key
 
switch($key){
    [VirtualKeyCode]::Q {
        Write-Host 'Q'
    }
    Default {
        Write-Host 'not Q'
    }
}
Вывод:
Code
1
2
True
not Q
Почему в switch-е [VirtualKeyCode]::Q не равно $key когда по -eq равно?
Если так
PowerShell
1
2
switch($key){
    {[VirtualKeyCode]::Q -eq $_} {
то будет правильно
Code
1
2
True
Q
Но почему?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
17.12.2024, 14:58
Ответы с готовыми решениями:

Switch and enum
Имеется такой код public class Solution { public static enum E1 {A, B, C, Y} public static enum E2 {D, E, F} ...

Switch по enum
есть некий enum который используется как флаговый, если установлены несколько полей то одно действие или другое... я хочу пройтись свитчем...

Switch case и enum
делаю калькулятор с помощью switch case у меня ошибку выдает на 20 строке bool plus = false; bool minus =...

29
 Аватар для alhaos
1929 / 545 / 154
Регистрация: 20.02.2019
Сообщений: 2,663
Записей в блоге: 65
17.12.2024, 17:55
Curry, Ответ на Ваш вопрос есть в документации

Все, что вы когда-либо хотели знать об инструкции switch

В вашем случае значение интерпретируется как строковой литерал

думаю корректно будет так

PowerShell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
enum VirtualKeyCode {
    D = 0x44
    Q = 0x51    
    S = 0x53 
}
 
$key = 0x51
 
switch($key){
    {[VirtualKeyCode]::Q}{
        Write-Host 'Q'
    }
    Default {
        Write-Host 'not Q'
    }
}
Code
1
Q
2
1658 / 273 / 66
Регистрация: 03.06.2020
Сообщений: 689
17.12.2024, 18:11
Поставьте фигурные скобки:

PowerShell
1
2
3
4
switch ($key) {
    { [VirtualKeyCode]::Q } { Write-Host 'Q' }
                            Default { Write-Host 'not Q' }
}
А, вы уже разобрались
2
Модератор
 Аватар для Curry
5154 / 3474 / 536
Регистрация: 01.06.2013
Сообщений: 7,532
Записей в блоге: 9
17.12.2024, 19:02  [ТС]
alhaos, зря я радовался и полез править настоящую программу
PowerShell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
enum VirtualKeyCode {
    D = 0x44
    Q = 0x51    
    S = 0x53 
}
 
 
$key = 123
 
switch($key){
    {[VirtualKeyCode]::Q}{
        Write-Host 'Q'
    }
    Default {
        Write-Host 'not Q'
    }
}
Вывод:
Code
1
Q
0
1658 / 273 / 66
Регистрация: 03.06.2020
Сообщений: 689
17.12.2024, 20:42
С полным синтаксисом работает корректно

PowerShell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
enum VirtualKeyCode
{
    D = 0x44
    Q = 0x51    
    S = 0x53 
}
 
# $key = 81
$key = 82
 
switch ($key)
{
    { $_ -eq [VirtualKeyCode]::Q } { Write-Host 'Q' }
                           Default { Write-Host 'not Q' }
}
0
Модератор
 Аватар для Curry
5154 / 3474 / 536
Регистрация: 01.06.2013
Сообщений: 7,532
Записей в блоге: 9
17.12.2024, 21:02  [ТС]
Цитата Сообщение от lesser Посмотреть сообщение
С полным синтаксисом работает корректно
Но тогда становится непонятно зачем использовать switch, можно if ... elseif ... else.
Cо switch без -eq выглядело бы аккуратно.
Работает так
PowerShell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
enum VirtualKeyCode {
    D = 0x44
    Q = 0x51    
    S = 0x53 
}
 
foreach ($key in  0x50 .. 0x52) {  
    switch([VirtualKeyCode].GetEnumName($key)){
        ([VirtualKeyCode]::Q){
            Write-Host 'Q'
        }
        Default {
            Write-Host 'not Q'
        }
    }    
}
Но переводить для сравнения в строки, это тоже извращение.
0
Любознательный
 Аватар для YuS_2
7404 / 2254 / 360
Регистрация: 10.03.2016
Сообщений: 5,214
17.12.2024, 21:46
Цитата Сообщение от Curry Посмотреть сообщение
Но переводить для сравнения в строки, это тоже извращение.
Строго говоря, не большее, чем сопоставление целочисленного значения с литеральной строкой.
Если вы хотите хранить все данные как строго типизированные перечисления, их можно взять в круглые скобки.
Т.е. это:
Цитата Сообщение от Curry Посмотреть сообщение
зря я радовался и полез править настоящую программу
Следовало записать так:
PowerShell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
enum VirtualKeyCode {
    D = 0x44
    Q = 0x51    
    S = 0x53 
}
 
 
$key = 123
 
switch($key){
    ([VirtualKeyCode]::Q){
        Write-Host 'Q'
    }
    Default {
        Write-Host 'not Q'
    }
}
и всё будет в шоколаде!

Добавлено через 9 минут
Да, чтобы сопоставлять с типизированным значением перечисления, необходимо и в переменную записывать именно типизированное значение:
PowerShell
1
$key = [VirtualKeyCode]0x51
как-то так...
1
1658 / 273 / 66
Регистрация: 03.06.2020
Сообщений: 689
17.12.2024, 22:00
Можно привести к одному типу:

PowerShell
1
2
3
4
5
switch ($key)
{ 
    $([int][VirtualKeyCode]::Q) { Write-Host 'Q' }
    default ( 'not Q' }
}
2
Модератор
 Аватар для Curry
5154 / 3474 / 536
Регистрация: 01.06.2013
Сообщений: 7,532
Записей в блоге: 9
17.12.2024, 22:05  [ТС]
Цитата Сообщение от YuS_2 Посмотреть сообщение
Следовало записать так:
Так всегда получается
Code
1
not Q
Цитата Сообщение от YuS_2 Посмотреть сообщение
$key = [VirtualKeyCode]0x51
Если такого кода нет, в enum вылетает
Code
1
2
    + CategoryInfo          : InvalidArgument: (:) [], RuntimeException
    + FullyQualifiedErrorId : UndefinedIntegerToEnum
А заносить все возможные коды клавиш в VirtualKeyCode не вижу смысла.

Добавлено через 3 минуты
Цитата Сообщение от lesser Посмотреть сообщение
Можно привести к одному типу:
Хм. Действительно, так работает. Даже так работает
PowerShell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
enum VirtualKeyCode {
    D = 0x44
    Q = 0x51    
    S = 0x53 
}
 
foreach ($key in  0x50 .. 0x52) {  
    switch($key){
        ([int][VirtualKeyCode]::Q){
            Write-Host 'Q'
        }
        Default {
            Write-Host 'not Q'
        }
    }    
}
(без $)
0
2802 / 500 / 120
Регистрация: 26.09.2020
Сообщений: 945
Записей в блоге: 5
18.12.2024, 02:12
Цитата Сообщение от Curry Посмотреть сообщение
Но почему?
видимо потому, что там строковый литерал, как выше указали, нужны скобки для «вычислений».
PowerShell
1
2
3
4
5
6
7
8
9
10
# пример 1. не Q
switch ([System.ConsoleKey]::Q) { [System.ConsoleKey]::Q { "Q" }; default { "не Q" } }
# пример 2. Q
switch ('[System.ConsoleKey]::Q') { [System.ConsoleKey]::Q { "Q" }; default { "не Q" } }
# пример 3. Q
switch ([System.ConsoleKey]::Q) { ([System.ConsoleKey]::Q) { "Q" }; default { "не Q" } }
# пример 4. Q
switch ('Q') { ([System.ConsoleKey]::Q) { "Q" }; default { "не Q" } }
# пример 5. Q
switch (81) { ([int][System.ConsoleKey]::Q) { "Q" }; default { "не Q" } }
А заносить все возможные коды клавиш в VirtualKeyCode не вижу смысла.
в этом и нет смысла, есть: [System.ConsoleKey], [System.ConsoleKeyInfo], [System.ConsoleModifiers], [System.ConsoleSpecialKey].
PowerShell
1
2
3
4
5
6
7
$k = [System.Console]::ReadKey($true)
 
switch ($k.Key) {
    ([System.ConsoleKey]::A) { $k.KeyChar }
    ([System.ConsoleKey]::Q) { $k.Key }
    default { "Неверные нажата клавиша" }
}
Узнал, что $k.KeyChar выводит с учётом языковой раскладки. Наверно где то пригодится
2
 Аватар для alhaos
1929 / 545 / 154
Регистрация: 20.02.2019
Сообщений: 2,663
Записей в блоге: 65
18.12.2024, 07:14
По моему слишком много специфических особенностей надо учитывать, мне наверное удобнее использовать словарь для этих целей.

PowerShell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$dict = [System.Collections.Generic.Dictionary[string, int]]::New()
$dict.Add("D", 0x44)
$dict.Add("Q", 0x51)
$dict.Add("S",  0x53)
 
$k = 0x51
 
switch($k){
    ($dict["Q"]){
        Write-Host 'Q'
    }
    Default {
        Write-Host 'not Q'
    }
}
Добавлено через 5 минут
Цитата Сообщение от YuS_2 Посмотреть сообщение
Следовало записать так:
PowerShell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
enum VirtualKeyCode {
    D = 0x44
    Q = 0x51    
    S = 0x53 
}
 
$key = 0x51
 
switch($key){
    ([VirtualKeyCode]::Q){
        Write-Host 'Q'
    }
    Default {
        Write-Host 'not Q'
    }
}
Code
1
not Q
1
Любознательный
 Аватар для YuS_2
7404 / 2254 / 360
Регистрация: 10.03.2016
Сообщений: 5,214
18.12.2024, 08:57
Цитата Сообщение от Curry Посмотреть сообщение
Если такого кода нет, в enum вылетает
Естественно, будет исключение.

Цитата Сообщение от Curry Посмотреть сообщение
А заносить все возможные коды клавиш в VirtualKeyCode не вижу смысла.
Тут надо отталкиваться от задачи, а потом выбирать подходящие средства. Powershell, конечно, имеет некую "интеллектуальность" в автоматической типизации, но в некоторых случаях, без принудиловки не обойтись.

Цитата Сообщение от alhaos Посмотреть сообщение
$key = 0x51
Другими словами, ты пытаешься сопоставлять теплое с кислым и удивляешься результату или чего ты хотел сказать? Говори уже прямо!
PowerShell
1
2
$key.gettype()
([VirtualKeyCode]::Q).gettype()
Добавлено через 5 минут
Цитата Сообщение от Curry Посмотреть сообщение
Действительно, так работает. Даже так работает
Потому, что так правильно, то бишь сопоставлять объекты одного типа...
0
 Аватар для alhaos
1929 / 545 / 154
Регистрация: 20.02.2019
Сообщений: 2,663
Записей в блоге: 65
18.12.2024, 10:22
YuS_2, ну... могу же я их сравнивать другими операторами, а тут я должен помнить про особенности сравнения

PowerShell
1
2
3
4
5
6
7
8
9
10
enum VirtualKeyCode {
    D = 0x44
    Q = 0x51
    S = 0x53 
}
 
[VirtualKeyCode]::Q -eq 0x51
"1" -eq 1
$true -eq 1
$true -eq "1"
Code
1
2
3
4
True
True
True
True
Добавлено через 11 минут
Как минимум не интуитивно, что вот эти две конструкции работают по разному

PowerShell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
enum VirtualKeyCode {
    D = 0x44
    Q = 0x51
    S = 0x53 
}
 
$key = 0x51
 
("no", "yes")[[VirtualKeyCode]::Q -eq $key]
 
switch ($key) {
    ([VirtualKeyCode]::Q) {"yes"}
    Default {"no"}
}
Code
1
2
yes
no
Добавлено через 7 минут
Как то "по своему" работает неявное приведение типов в этой конструкции

PowerShell
1
2
3
4
5
6
7
8
9
10
11
$false -eq 0
switch ($false) {
    0 {$true}
    Default {$false}
}
 
"1" -eq 1
switch ("1") {
    1 {$true}
    Default {$false}
}
Code
1
2
3
4
True
False
True
True
1
Любознательный
 Аватар для YuS_2
7404 / 2254 / 360
Регистрация: 10.03.2016
Сообщений: 5,214
18.12.2024, 10:49
Цитата Сообщение от alhaos Посмотреть сообщение
могу же я их сравнивать другими операторами
можешь. Можешь даже строки с числом сравнивать...
PowerShell
1
"1" -eq 1
- что само по себе нонсенс...
Поэтому не забывай, что при таком сравнении работает автотипизация, которая может не работать внутри конструкции switch ... это же powershell

Добавлено через 11 минут
alhaos, я тебе даже больше скажу...
Сравнивать можно коллекцию и единичный объект (скаляр)
PowerShell
1
"zzz", "def", "zzz" -eq "zzz"
В общем, если таки почитать документацию, то можно увидеть там явное упоминание:
Оператор равенства может сравнить объекты разных типов. Важно понимать, что значение в правой части сравнения можно преобразовать в тип левого значения для сравнения.
Тут где-то был топик, который я стартанул про сравнения дробных чисел, там вообще труба... ща найду...
Вот
Так что сравнение сопоставлению рознь
1
Модератор
 Аватар для Curry
5154 / 3474 / 536
Регистрация: 01.06.2013
Сообщений: 7,532
Записей в блоге: 9
18.12.2024, 12:21  [ТС]
Цитата Сообщение от iNNOKENTIY21 Посмотреть сообщение
$k = [System.Console]::ReadKey($true)
switch ($k.Key) {
    ([System.ConsoleKey]::A) { $k.KeyChar }
    ([System.ConsoleKey]::Q) { $k.Key }
    default { "Неверные нажата клавиша" }
}
Если выкинуть System. , т.е.
PowerShell
1
2
3
4
5
6
7
8
            Write-Host 'Type [R]escan or [Q]uit.'
            :lWaitKey for(;;){
                $key=[Console]::ReadKey($true)
                switch ($key.key) {
                    ([ConsoleKey]::Q) { exit 1 }
                    ([ConsoleKey]::R) { break lWaitKey}
                }
            }
То тоже работает.
Или, может, выкидывать System., это в PS некошерно?
0
1658 / 273 / 66
Регистрация: 03.06.2020
Сообщений: 689
18.12.2024, 13:35
Цитата Сообщение от Curry Посмотреть сообщение
Или, может, выкидывать System., это в PS некошерно?
Это допустимо, так как это корневой токен в иерархии, есть и другие, но парсер учитывает отсутствие "System"

Добавлено через 2 минуты
PS. Не всегда, зависит от синтаксической конструкции.
1
Любознательный
 Аватар для YuS_2
7404 / 2254 / 360
Регистрация: 10.03.2016
Сообщений: 5,214
18.12.2024, 14:03
Цитата Сообщение от Curry Посмотреть сообщение
Или, может, выкидывать System., это в PS некошерно?
В PS всё кошерно, что работает правильно. Пространство имен System. можно опускать, для PS это будет понятно.
А вообще, в PS можно даже акселераторы создавать:
PowerShell
1
[psobject].assembly.gettype("System.Management.Automation.TypeAccelerators")::get
- список доступных акселераторов
или кастомный создать:
PowerShell
1
2
3
$accels = [powershell].assembly.gettype("System.Management.Automation.TypeAccelerators")
$accels::add("ConKey","System.ConsoleKey")
[conkey]
чем powershell и хорош...
3
 Аватар для alhaos
1929 / 545 / 154
Регистрация: 20.02.2019
Сообщений: 2,663
Записей в блоге: 65
18.12.2024, 14:48
Цитата Сообщение от YuS_2 Посмотреть сообщение
Тут где-то был топик, который я стартанул про сравнения дробных чисел, там вообще труба... ща найду...
это тебя не туда понесло, это особенность математики float чисел
0
Любознательный
 Аватар для YuS_2
7404 / 2254 / 360
Регистрация: 10.03.2016
Сообщений: 5,214
18.12.2024, 15:45
Цитата Сообщение от alhaos Посмотреть сообщение
это тебя не туда понесло, это особенность математики float чисел
там, как раз, есть про сравнение и автоприведение типов... так что всё нормально, никуда меня не заносило, просто читай внимательнее

Добавлено через 19 минут
вот, собственно, ссылка оттуда
0
Модератор
 Аватар для Curry
5154 / 3474 / 536
Регистрация: 01.06.2013
Сообщений: 7,532
Записей в блоге: 9
18.12.2024, 16:00  [ТС]
Цитата Сообщение от YuS_2 Посмотреть сообщение
Так что сравнение сопоставлению рознь
Приведение типов, это одно
PowerShell
1
2
3
4
5
[byte]$a,$b=2,3
$a.GetType().FullName
$b.GetType().FullName
($a*$b).GetType().FullName
"1"+1
Вывод:
Code
1
2
3
4
System.Byte
System.Byte
System.Int32
11
Но от switch-а я всё таки интуитивно ожидал что он будет эквивалентен обычным сравнениям выражения внутри switch() со всеми его вариантами.

Не по теме:

ps. Тех кто пользуется светлой темой форума не раздражает что символы пунктуации отображаемые светло-морковным цветом практически не видны?

0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
18.12.2024, 16:00
Помогаю со студенческими работами здесь

Enum ломается в операторе Switch
Добрый вечер форумчане, нужен ваш бесценный совет для начинающего программиста. Есть в задании один момент, который не дает мне покоя:...

enum, switch/case и socket
дан enum packet { LetsPlay, StartConfirmed, StartDeclined }; далее пытаюсь его использовать void __fastcall...

Перечисляемый тип enum + switch
Всем привет, прошу помочь разобраться, делаю структуры и все никак не могу сделать так , чтобы заработал фрагмент программы связанный с...

Игра с использованием do while + enum + switch
Условие игры - стрелять до тех пор, пока человечек не умрет (здоровье < 0) либо мы спасаем его, не давая умереть. Изначальный уровень...

ENUM в {SWITCH.CASE} не работает с атрибутами
Имеется следующий enum: public enum ComboBoxContents { WIRE, MOTOR_PROTECTION_CB,


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
http://iceja.net/ математические сервисы
iceja 20.01.2026
Обновила свой сайт http:/ / iceja. net/ , приделала Fast Fourier Transform экстраполяцию сигналов. Однако предсказывает далеко не каждый сигнал (см ограничения http:/ / iceja. net/ fourier/ docs ). Также. . .
http://iceja.net/ сервер решения полиномов
iceja 18.01.2026
Выкатила http:/ / iceja. net/ сервер решения полиномов (находит действительные корни полиномов методом Штурма). На сайте документация по API, но скажу прямо VPS слабенький и 200 000 полиномов. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь(не выше 3-го порядка) постоянного тока с элементами R, L, C, k(ключ), U, E, J. Программа находит переходные токи и напряжения на элементах схемы классическим методом(1 и 2 з-ны. . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru