Почему назначения переменных внутри блока Trap не видны вне его? - PullRequest
4 голосов
/ 04 января 2010

Почему переменные назначения, которые я делаю внутри блока Trap, не видны за его пределами?

$integer = 0;
$string = [String]::Empty;
$stringBuilder = new-object 'System.Text.StringBuilder';

trap
{
    $integer = 1;
    $string = '1';
    $stringBuilder.Append('1');

    write-host "Integer Variable Inside: " $integer;
    write-host "String Variable Inside: " $string;
    write-host "StringBuilder Variable Inside: " $stringBuilder;

    continue;
}
$dummy = 1/$zero;

write-host "Integer Variable Outside: " $integer;
write-host "String Variable Outside: " $string;
write-host "StringBuilder Variable Outside: " $stringBuilder;

Я бы ожидал, что результаты внутри и снаружи блока Trap будут одинаковыми, но это те результаты, которые я вижу.

Integer Variable Inside:  1
String Variable Inside:  1
StringBuilder Variable Inside:  1
Integer Variable Outside:  0
String Variable Outside:
StringBuilder Variable Outside:  1

Обратите внимание, что только StringBuilder сохраняет свое значение.

Я предполагаю, что это как-то связано с разницей между типом значения и ссылочным типом, но не может точно определить это.

Ответы [ 2 ]

4 голосов
/ 05 января 2010

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

Джоэл объясняет , как работает область Trap следующим образом.

Хотя в нашем обработчике ошибок мы были в состоянии получить доступ к значению $ Результат и убедитесь, что это правда ... и хотя мы установили его в $ False, и распечатал, чтобы вы могли видеть, что это было установить ... функция все еще возвращает True, потому что объем ловушки не изменяется внешняя сфера, если вы явно установить область действия переменная. ПРИМЕЧАНИЕ: если вы использовали $ script: результат вместо $ result (в каждый случай, когда появляется $ result в этом сценарии), вы получите вывод, который вел строка / комментарии Вас ожидать.

Таким образом, переменные за пределами области действия Trap могут быть прочитаны, но не установлены, поскольку они являются копиями оригиналов (спасибо Джейсон ). По этой причине переменная Integer не сохранила свое значение. Однако StringBuilder является ссылочным объектом, а переменная является только указателем на этот объект. Код в области действия Trap смог прочитать ссылку, на которую была установлена ​​переменная, и изменить объект, на который она указывала - сама переменная не требовала изменений.

Обратите внимание, что совет Джоэла об определении области действия переменной позволил мне установить значение переменной Integer из области действия Trap.

$ script: целое число = 0; $ string = [String] :: Empty; $ stringBuilder = новый объект 'System.Text.StringBuilder';

trap
{
    $script:integer = 1;
    $string = '1';
    $stringBuilder.Append('1');

    write-host "Integer Variable Inside: " $script:integer;
    write-host "String Variable Inside: " $string;
    write-host "StringBuilder Variable Inside: " $stringBuilder;
    continue;
}
$dummy = 1/$zero;

write-host "Integer Variable Outside: " $script:integer;
write-host "String Variable Outside: " $string;
write-host "StringBuilder Variable Outside: " $stringBuilder;

... и вот результаты.

Integer Variable Inside:  1
String Variable Inside:  1
StringBuilder Variable Inside:  1
Integer Variable Outside:  1
String Variable Outside:
StringBuilder Variable Outside:  1

Обратите внимание, что строковая переменная не сохраняет своего значения, потому что, хотя это ссылочный тип, она также неизменна.

2 голосов
/ 05 января 2010

Вместо того, чтобы переписать отличный пост Якула на эту тему, я просто сошлюсь на него: http://huddledmasses.org/trap-exception-in-powershell/

Информация о том, как powershell справляется с обработкой ошибок, с большим количеством деталей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...