2015-06-05 3 views
1

У меня есть функция, которая возвращает значение глобальной переменной. Когда я назначаю этот результат локальной переменной и изменяя локальное значение, меняется и другая переменная.Почему Изменение значения локальной переменной влияет на глобальную копию

Пример:

function setGlobal 
{ 
    $temp = @{} 

    $temp.id = 50; 

    $Global:global1 = $temp; 

    return $Global:global1; 
} 

потом вызывать эту функцию, и установить значение результата:

$result = setGlobal 
$result.id = 80 

теперь обе переменные имеет то же значение.

$Global:global1 # id = 60 
$result # id = 60 

Как я могу предотвратить это? И почему изменение локального значения повлияет на глобальную копию?

+1

Локальное изменение глобального, потому что на самом деле у вас есть две вещи: переменная и набор, на которые указывает переменная. вы не изменяете переменную, содержащую коллекцию, вы сами изменяете ее. –

ответ

3

Причина в том, , конечно, что у вас нет двух копий объекта. У вас есть две ссылки на один и тот же объект - хеш-таблицу. Ссылка копируется, а не объект. Объект подобен дому. Переменные (global1 и результат) похожи на кусочки бумаги. Я пишу адрес дома на своем листе бумаги (global1), а затем копирую адрес на лист бумаги (результат). Затем переходите к адресу, который у вас есть, и красите дверь красной. Теперь, когда я иду на адрес, который у меня есть, и у моего дома теперь есть красная дверь.

Создание глубокой копии объекта несколько проще, чем создание копии дома. Для произвольного использования объекта PSObject.Copy():

function setGlobal 
{ 
    $temp = @{} 
    $temp.id = 50; 
    $Global:global1 = $temp; 
    return $Global:global1.PSObject.Copy(); 
} 

В этом случае, это точно так же, как клон, поскольку PSObject.Copy использует клон, если он доступен.

2

Это происходит потому, что powershell неявно использует ссылки. Таким образом, $Global:global1 и $result в конечном итоге указывают на то же место, когда вы выполняете задание.

Чтобы получить копию, используйте .Clone() метод:

$result = $Global:global1.Clone() 

Или вместо того, чтобы делать, что на уступки, сделать это в возвращении функции:

function setGlobal 
{ 
    $temp = @{} 

    $temp.id = 50; 

    $Global:global1 = $temp; 

    return $Global:global1.Clone(); 
} 
Смежные вопросы