Почему переменная, определенная локально, успешно доступна из другой функции? - PullRequest
0 голосов
/ 02 октября 2018

См. Код ниже.Поместите оба файла в один и тот же каталог и запустите Form1.ps1 от PS ISE

. Как видите, (локальная) переменная $localVar определена в обработчике событий $button2_Click.Таким образом, я предположил, что $localVar не будет / не может существовать вне области действия $button2_Click с областью действия, определенной скобками, определяющими обработчик событий.

Однако, как вы можете видеть, я использую содержимое$localVar для загрузки $textbox2.Text в функции fA.Когда вы нажимаете кнопку Test, в обоих текстовых полях отображается содержимое $localVar

Что происходит?Почему $button2_Click $localVar доступен из fA?

Form1.ps1

function fA
{
    $textbox2.Text = $localVar
}

$button2_Click = 
{
    $localVar = "set in `$button2_Click"
    $textbox1.Text = $localVar
    fA
}

. (Join-Path $PSScriptRoot 'Form1.designer.ps1')

$textbox1.Text = ""
$Form1.ShowDialog()

Form1.designer.ps1

[void][System.Reflection.Assembly]::Load('System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a')
[void][System.Reflection.Assembly]::Load('System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089')
$Form1 = New-Object -TypeName System.Windows.Forms.Form
[System.Windows.Forms.Button]$button2 = $null
[System.Windows.Forms.TextBox]$textBox1 = $null
[System.Windows.Forms.TextBox]$textBox2 = $null
[System.Windows.Forms.Label]$label1 = $null
[System.Windows.Forms.Label]$label2 = $null
[System.Windows.Forms.Button]$button1 = $null
function InitializeComponent
{
$button2 = (New-Object -TypeName System.Windows.Forms.Button)
$textBox1 = (New-Object -TypeName System.Windows.Forms.TextBox)
$textBox2 = (New-Object -TypeName System.Windows.Forms.TextBox)
$label1 = (New-Object -TypeName System.Windows.Forms.Label)
$label2 = (New-Object -TypeName System.Windows.Forms.Label)
$Form1.SuspendLayout()
#
#button2
#
$button2.Location = (New-Object -TypeName System.Drawing.Point -ArgumentList @([System.Int32]148,[System.Int32]12))
$button2.Name = [System.String]'button2'
$button2.Size = (New-Object -TypeName System.Drawing.Size -ArgumentList @([System.Int32]77,[System.Int32]36))
$button2.TabIndex = [System.Int32]0
$button2.Text = [System.String]'Test'
$button2.UseVisualStyleBackColor = $true
$button2.add_Click($button2_Click)
#
#textBox1
#
$textBox1.Location = (New-Object -TypeName System.Drawing.Point -ArgumentList @([System.Int32]67,[System.Int32]69))
$textBox1.Name = [System.String]'textBox1'
$textBox1.Size = (New-Object -TypeName System.Drawing.Size -ArgumentList @([System.Int32]106,[System.Int32]20))
$textBox1.TabIndex = [System.Int32]1
#
#textBox2
#
$textBox2.Location = (New-Object -TypeName System.Drawing.Point -ArgumentList @([System.Int32]247,[System.Int32]69))
$textBox2.Name = [System.String]'textBox2'
$textBox2.Size = (New-Object -TypeName System.Drawing.Size -ArgumentList @([System.Int32]106,[System.Int32]20))
$textBox2.TabIndex = [System.Int32]2
#
#label1
#
$label1.AutoSize = $true
$label1.Location = (New-Object -TypeName System.Drawing.Point -ArgumentList @([System.Int32]12,[System.Int32]72))
$label1.Name = [System.String]'label1'
$label1.Size = (New-Object -TypeName System.Drawing.Size -ArgumentList @([System.Int32]47,[System.Int32]13))
$label1.TabIndex = [System.Int32]3
$label1.Text = [System.String]'textbox1'
#
#label2
#
$label2.AutoSize = $true
$label2.Location = (New-Object -TypeName System.Drawing.Point -ArgumentList @([System.Int32]194,[System.Int32]72))
$label2.Name = [System.String]'label2'
$label2.Size = (New-Object -TypeName System.Drawing.Size -ArgumentList @([System.Int32]47,[System.Int32]13))
$label2.TabIndex = [System.Int32]4
$label2.Text = [System.String]'textbox2'
#
#Form1
#
$Form1.ClientSize = (New-Object -TypeName System.Drawing.Size -ArgumentList @([System.Int32]374,[System.Int32]110))
$Form1.Controls.Add($label2)
$Form1.Controls.Add($label1)
$Form1.Controls.Add($textBox2)
$Form1.Controls.Add($textBox1)
$Form1.Controls.Add($button2)
$Form1.Name = [System.String]'Form1'
$Form1.ResumeLayout($false)
$Form1.PerformLayout()
Add-Member -InputObject $Form1 -Name base -Value $base -MemberType NoteProperty
Add-Member -InputObject $Form1 -Name button2 -Value $button2 -MemberType NoteProperty
Add-Member -InputObject $Form1 -Name textBox1 -Value $textBox1 -MemberType NoteProperty
Add-Member -InputObject $Form1 -Name textBox2 -Value $textBox2 -MemberType NoteProperty
Add-Member -InputObject $Form1 -Name label1 -Value $label1 -MemberType NoteProperty
Add-Member -InputObject $Form1 -Name label2 -Value $label2 -MemberType NoteProperty
Add-Member -InputObject $Form1 -Name button1 -Value $button1 -MemberType NoteProperty
}
. InitializeComponent

Ответы [ 2 ]

0 голосов
/ 02 октября 2018

Функция fA видит вашу переменную, потому что она выполняется в области действия child блока сценария, в котором был создан $localVar - это общее поведение PowerShell, а не специфичное для ISE.

Когда вы создаете переменную с $localVar = ..., это локально в следующем смысле:

  • видимый и непосредственно изменяемый в той же области видимости, но не в любой родительской областях.

  • видимый в всех дочерних областях, но не может быть изменен напрямую.

    • Вы можете использовать модификатор области $private:, чтобы предотвратить дочерниене видят переменную.
    • Если вы назначите переменную (только по имени), которая была первоначально создана в parent scope (например, $localVar = ...), вы вместо этогосоздайте новую локальную переменную в области действия current , которая затеняет исходную переменную.
    • Это возможно в режимеПеременные родительской области видимости, но вам нужно использовать либо Set-Variable -Scope, либо модификатор области видимости, например $script: (см. ссылки ниже).

Для получения дополнительной информации см.:

0 голосов
/ 02 октября 2018

Здравствуйте. Итак, в ISE у вас есть вкладки Powershell и вкладки скриптов.

Вкладка Powershell похожа на работу с одной консолью Powershell.Каждая вкладка «Сценарий» внутри этой вкладки powershell использует эту консоль.Так что, если в одном скрипте вы определите

$Hello = "TEST"

, запустите его в ise.Затем в другой вкладке скрипта на той же вкладке powershell вы запускаете

$ Hello

, вывод будет "TEST"

Это называется Scope.В основном то, что код переменных может видеть.Все переменные, созданные в экземпляре powershell, всегда доступны в остальной части этого экземпляра

Так что давайте немного углубимся и рассмотрим пример

function fA
{
    $textbox2.Text = $localVar
}

$button2_Click = 
{
    $localVar = "123"
    $textbox1.Text = $localVar
    fA
}

$ localVar создается по щелчку дляпервый раз.Область действия будет продолжаться от всего, что создано после него.Таким образом, вызывается FA, а $ localvar переносится в область действия FA.Текстовые поля 1 и 2 показывают 123. Но давайте покажем, как все еще есть область для этого, и она не глобальна.

function TB1
{
    $localVar = "456"
    $textbox1.Text = $localVar # Will output 456
}

function TB2{
    $textbox2.Text = $localVar # Will output 123
}
$button2_Click = 
{
    $localVar = "123"
    TB1
    TB2
    fA
}

$ localVar , созданный впервые.Переданная первой функции $ localvar по-прежнему 123 , но в функции она изменилась на 456 .Когда он уходит, он переходит ко второй функции, где его $ Localvar будет равен 123 .Переменная, измененная в функции, не влияла на переменную, которая была в ее родительском, называемом вызывающим button2_click

...