Я пишу класс PowerShell следующим образом:
class FileTransferStatus {
$totalBytesToTransfer
$bytesLeftToTransfer
FileTransferStatus([System.IO.FileInfo[]]$files)
{
this.$totalBytesToTransfer = 0
foreach ($file in $files) {
this.$totalBytesToTransfer += $file.length
}
this.$bytesLeftToTransfer = this.$totalBytesToTransfer
}
}
Я получаю сообщение об ошибке в последней строке конструктора, который пытается инициализировать $bytesLeftToTransfer. Сообщение: переменная не назначена в методе.
Кто-нибудь знает, что означает это сообщение или как решить проблему?
Ух ты. Я не могу сказать вам, как долго я смотрел на этот экран, не замечая неуместного знака доллара. Конечно, загадочное сообщение об ошибке мало чем помогло. Но хорошо то, что хорошо кончается. Спасибо за быстрое обращение!
Примечание для потенциальных избирателей: хотя для тех, кто близко знаком с PowerShell, это может показаться простой опечаткой, для менее посвященных есть проблемы с синтаксисом, которые стоит изучить, поэтому я предлагаю оставить этот вопрос открытым.





Сантьяго Скварзон предоставил ключевой указатель в комментарии:
this.$totalBytesToTransfer должны быть $this.totalBytesToTransfer.Хотя пользователям, уже знакомым с PowerShell class, ваш код может показаться простой опечаткой, требуемый синтаксис стоит объяснить:
Автоматическая переменная $this относится к экземпляру под рукой.
Чтобы обратиться к свойству экземпляра под рукой, вы должны использовать $this в сочетании с обычной точечной нотацией , но без префикса $- перед именем свойства — даже если свойства должны быть объявлены с этим префиксом; то есть:
Чтобы объявить свойство с именем TotalBytesToTransfer, вы должны использовать синтаксис переменных, который требует $: $TotalBytesToTransfer
(обычно объявляется с типом, например, [long] $TotalBytesToTransfer).
Чтобы получить доступ к этому свойству, вы должны использовать $this.TotalBytesToTransfer
Удивительные аспекты:
По сравнению с С#:
this - $this - для ссылки на свойства экземпляра, что является необязательным в C# (как для свойств, так и для полей; последние не имеют аналога в PowerShell).По сравнению с другими частями PowerShell:
class, не являются неявно в области видимости как таковой в методах экземпляра, в то время как примерно аналогичные переменные, определяющие параметры, в функциях и скриптах.Что касается того, что вы пробовали:
Кто-нибудь знает, что означает это сообщение?
Сообщение об ошибке Variable is not assigned in the method. пытается сообщить вам, что внутри данного метода вы попытались сослаться на переменную, которая не была определена ранее в том же методе, что было вызвано случайной ссылкой на несуществующую переменную $totalBytesToTransfer.
Как отмечалось выше, переменные, определяющие свойство, не доступны неявно, и любые ссылки на переменные должны относиться к локальным переменным метода, то есть к переменным, определенным ранее в том же методе.
$global:foo; однако таких ссылок лучше избегать в классах, чтобы не нарушать инкапсуляцию.Сообщение об ошибке, указанное в PowerShell 7.3.4, может быть улучшено, что является предметом выпуска GitHub # 19767.
Причина, по которой только последняя из четырех ваших ссылок this.$totalBytesToTransfer вызвала ошибку, коренится в основах синтаксиса PowerShell, который сочетает в себе синтаксис, подобный оболочке, с синтаксисом, знакомым из традиционных языков программирования, с помощью различных режимов синтаксического анализа (см. общую информацию в нижней части):
Возможно, это покажется вам удивительным, но this.$totalBytesToTransfer допустимо как дословное имя команды в PowerShell, то есть как идентификатор в начале инструкции, поэтому проблем с синтаксисом не возникает.
Например, вы можете определить функцию с буквальным именем this.$totalBytesToTransfer и вызвать ее:
function this.$totalBytesToTransfer { 'hi!' }
this.$totalBytesToTransfer # -> 'hi!'
Однако, когда тот же токен используется в качестве аргумента команды, $totalBytesToTransfer будет расширяться (интерполироваться), т. е. рассматриваться как ссылка на переменную; то есть this.$totalBytesToTransfer неявно обрабатывается как расширяемая (в двойных кавычках) строка ("..."):
$totalBytesToTransfer = 42
Write-Output this.$totalBytesToTransfer # -> 'this.42'
Учитывая вышеизложенное, ваши токены this.$totalBytesToTransfer интерпретируются следующим образом:
# Call to (hypothetical) command 'this.$totalBytesToTransfer'
# with arguments '=' and 0
this.$totalBytesToTransfer = 0
# Call to (hypothetical) command 'this.$totalBytesToTransfer'
# with arguments '+=' and the value of the .length property of the
# object stored in variable $file.
this.$totalBytesToTransfer += $file.length
# Call to (hypothetical) command 'this.$totalBytesToTransfer'
# with arguments '=' and the concatenation of 'this.' and the
# the value of a (hypothetical) $totalBytesToTransfer variable.
this.$bytesLeftToTransfer = this.$totalBytesToTransfer
В последнем утверждении выше гипотетическая переменная $totalBytesToTransfer ранее не была определена внутри рассматриваемого метода, что приводит к тому, что PowerShell сообщает об ошибке, которую вы видели.
Как правило, обратите внимание, что PowerShell — как оболочка и (очень функциональный) язык сценариев — по необходимости должен объединить два различных синтаксических мира:
Это требует двух разных режимов синтаксического анализа, как описано в разделе about_Parsing.
Вкратце: начало каждого оператора определяет, какой из двух режимов синтаксического анализа применяется, что также относится к вложенным операторам. См. этот ответ для получения справочной информации.
Большое спасибо, что нашли время, чтобы дать такой исчерпывающий ответ. Мне особенно понравились ваши сравнения с другими языками. Я думаю, что мои годы знакомства с Java и C++, возможно, способствовали тому, что я использовал неправильный синтаксис. Но сейчас вроде все хорошо. Еще раз спасибо!
Я вижу только серую стрелку вверх и серый флажок под ней.
Яйцо на моем лице. Оказывается, я смотрел «комментарий» к своему исходному сообщению. Вот где я увидел единственную стрелку вверх и флаг. Это «ответы», которые имеют стрелки вверх и вниз и галочку. До сих пор учусь пользоваться форумом спустя столько лет.
@aksarben: 😁 Не беспокойся. Я рад, что мы добрались туда.
у вас 4 опечатки:
this.$totalBytesToTransferдолжно быть$this.totalBytesToTransfer