Чому глобальна змінна читається, але не записується всередині функції?


0

Наступний сценарій оболонки повноважень виведе A, B, A

$x = "A"

function scopetest()
{
    Write-Host $x;
    $x = 'B'
    Write-Host $x
}

scopetest

Write-Host $x

Тепер дивна частина:

Перше значення A - з глобальної області - воно може бути прочитане всередині функції, тому очевидно, що змінна присутня. Однак якщо я записую в змінну як є, значення B не зберігається поза функцією.

Я б очікував одного з цих двох результатів: [null], B, A або A, B, B (останній досягається, якщо я пишу за допомогою $ global: x = 'B' ).

Чому глобальна змінна $ x читається всередині функції, але не записується?



2
"команди, виконані в одному діапазоні, не впливатимуть на речі в іншій області, якщо спеціально не сказано про це. Наприклад, якщо $ MyVar існує в глобальній області і сценарій виконує команду встановити $ MyVar на інше значення, глобальна версія $ MyVar залишиться незмінним, поки копія $ MyVar буде розміщена в області Скрипту з новим значенням ".
DavidPostill

У вас є глобальний $xі локальний$x
DavidPostill

1
@DavidPostill, я вважав те саме на перших порах, але згідно з технологією, пункти з глобальним набором є членами локальної області, тому не повинно існувати можливості для подвійного розподілу без зіткнення імен. натомість це лише незвичайні правила обробки сфери Powershells.
Френк Томас

2
@mhbuur, тому що саме так було визначено мовну мову. Існують численні підходи, складені та написані сценаріями мов, які прив'язують імена до розподілу пам'яті, і всі вони мають різні правила. Powershell, оскільки це керований час виконання, може застосовувати правила сфери застосування, які вони вважають бажаними. У цьому випадку посиденька сценаріїв або включення заздалегідь написаної функції до нового сценарію суттєво менш небезпечні, якщо обмежити мутацію сферою володіння.
Френк Томас

Відповіді:


2

З https://technet.microsoft.com/en-us/library/hh847849.aspx

Елемент, створений вами в межах області, може бути змінений лише в тій області, в якій він був створений, якщо ви прямо не вказали іншу область.

так що ви можете використовувати його $Global:x = ...для встановлення.

Сценарії Powershell часто копіюються та вставляються в блоки для реалізації функціональності, і часто методи написані для використання у кількох сценаріях. Обмежуючи присвоєння визначеній області для змінної, ви гарантуєте, що навіть якщо два вставлені блоки коду використовують одне і те ж ім'я змінної, вони не можуть неналежним чином змінити дані, від яких залежить інший блок, не чітко заявляючи, що вони цього хочуть. Це допомагає зробити блоки більш модульними, а також виявити ненавмисні зіткнення імен.

Редагувати:

примітка про сферу повноважень: Потужність каскадів Powershell, тому локальна область дії завжди містить об'єкти, визначені в областях пращурів (батьківський, прозорий, глобальний тощо). Це означає, що змінна, визначена в усьому світі або в батьківському пакеті стека (функція, що викликає функцію), завжди доступна, тоді як об'єкти, визначені в дочірніх областях, не є. У цьому випадку єдиним обмеженням є те, що дочірня область не може змінювати значення батьківського діапазону, якщо тільки ця область не визначена прямо.

Від: https://technet.microsoft.com/en-us/library/hh847849.aspx

Нижче наведені основні правила застосування:

    - An item you include in a scope is visible in the scope in which it 
      was created and in any child scope, unless you explicitly make it 
      private. You can place variables, aliases, functions, or Windows
      PowerShell drives in one or more scopes. 

    - An item that you created within a scope can be changed only in the 
      scope in which it was created, unless you explicitly specify a 
      different scope.


If you create an item in a scope, and the item shares its name with an
item in a different scope, the original item might be hidden under the
new item. But, it is not overridden or changed.

Правильно, тому це стосується лише зміни значення, а не читання значення.
mhbuur

це правильно.
Френк Томас
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.