Конструктор класса PowerShell — невозможно присвоить значение переменной

Я пишу класс 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. Сообщение: переменная не назначена в методе.

Кто-нибудь знает, что означает это сообщение или как решить проблему?

у вас 4 опечатки: this.$totalBytesToTransfer должно быть $this.totalBytesToTransfer

Santiago Squarzon 06.06.2023 21:16

Ух ты. Я не могу сказать вам, как долго я смотрел на этот экран, не замечая неуместного знака доллара. Конечно, загадочное сообщение об ошибке мало чем помогло. Но хорошо то, что хорошо кончается. Спасибо за быстрое обращение!

aksarben 06.06.2023 23:25

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

mklement0 08.06.2023 00:23
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
3
65
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Сантьяго Скварзон предоставил ключевой указатель в комментарии:

  • Вместо этого все экземпляры this.$totalBytesToTransfer должны быть $this.totalBytesToTransfer.

Хотя пользователям, уже знакомым с PowerShell class, ваш код может показаться простой опечаткой, требуемый синтаксис стоит объяснить:

  • Автоматическая переменная $this относится к экземпляру под рукой.

  • Чтобы обратиться к свойству экземпляра под рукой, вы должны использовать $this в сочетании с обычной точечной нотацией , но без префикса $- перед именем свойства — даже если свойства должны быть объявлены с этим префиксом; то есть:

    • Чтобы объявить свойство с именем TotalBytesToTransfer, вы должны использовать синтаксис переменных, который требует $: $TotalBytesToTransfer
      (обычно объявляется с типом, например, [long] $TotalBytesToTransfer).

    • Чтобы получить доступ к этому свойству, вы должны использовать $this.TotalBytesToTransfer

Удивительные аспекты:

  • По сравнению с С#:

    • PowerShell требует эквивалента 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 — как оболочка и (очень функциональный) язык сценариев — по необходимости должен объединить два различных синтаксических мира:

  • команды оболочки (команды, за которыми следуют аргументы, разделенные пробелами) vs.
  • выражения (операторные операции и вызовы методов), как в традиционных языках программирования).

Это требует двух разных режимов синтаксического анализа, как описано в разделе about_Parsing.

Вкратце: начало каждого оператора определяет, какой из двух режимов синтаксического анализа применяется, что также относится к вложенным операторам. См. этот ответ для получения справочной информации.

Большое спасибо, что нашли время, чтобы дать такой исчерпывающий ответ. Мне особенно понравились ваши сравнения с другими языками. Я думаю, что мои годы знакомства с Java и C++, возможно, способствовали тому, что я использовал неправильный синтаксис. Но сейчас вроде все хорошо. Еще раз спасибо!

aksarben 08.06.2023 05:58

Я вижу только серую стрелку вверх и серый флажок под ней.

aksarben 08.06.2023 21:07

Яйцо на моем лице. Оказывается, я смотрел «комментарий» к своему исходному сообщению. Вот где я увидел единственную стрелку вверх и флаг. Это «ответы», которые имеют стрелки вверх и вниз и галочку. До сих пор учусь пользоваться форумом спустя столько лет.

aksarben 09.06.2023 01:41

@aksarben: 😁 Не беспокойся. Я рад, что мы добрались туда.

mklement0 09.06.2023 01:44

Другие вопросы по теме