about_Classes_Properties
Краткое описание
Описание определения свойств для классов PowerShell.
Подробное описание
Свойства являются членами класса, содержащего данные. Свойства объявляются как переменные в области класса. Свойство может быть любого встроенного типа или экземпляра другого класса. Классы могут нулю или больше свойств. Классы не имеют максимального количества свойств.
Свойства класса могут иметь любое количество атрибутов, включая скрытые и статические атрибуты. Каждое определение свойства должно содержать тип для свойства. Можно определить значение по умолчанию для свойства.
Синтаксис
Свойства класса используют следующие синтаксисы:
Однострочный синтаксис
[[<attribute>]...] [<property-type>] $<property-name> [= <default-value>]
Синтаксис с несколькими линиями
[[<attribute>]...]
[<property-type>]
$<property-name> [= <default-value>]
Примеры
Пример 1. Минимальные свойства класса
Свойства класса ExampleProject1 используют встроенные типы без атрибутов или значений по умолчанию.
class ExampleProject1 {
[string] $Name
[int] $Size
[bool] $Completed
[string] $Assignee
[datetime] $StartDate
[datetime] $EndDate
[datetime] $DueDate
}
[ExampleProject1]::new()
$null -eq ([ExampleProject1]::new()).Name
Name :
Size : 0
Completed : False
StartDate : 1/1/0001 12:00:00 AM
EndDate : 1/1/0001 12:00:00 AM
DueDate : 1/1/0001 12:00:00 AM
True
Значение по умолчанию для свойств Name и Assignee заключается $null
в том, что они типизовываются как строки, которые являются ссылочным типом. Другие свойства имеют значение по умолчанию для определенного типа, так как они имеют свойства типа значений. Дополнительные сведения о значениях по умолчанию для свойств см. в разделе "Значения свойств по умолчанию".
Пример 2. Свойства класса с пользовательскими типами
Свойства для ExampleProject2 включают пользовательское перечисление и класс, определенный в PowerShell перед классом ExampleProject2 .
enum ProjectState {
NotTriaged
ReadyForWork
Committed
Blocked
InProgress
Done
}
class ProjectAssignee {
[string] $DisplayName
[string] $UserName
[string] ToString() {
return "$($this.DisplayName) ($($this.UserName))"
}
}
class ExampleProject2 {
[string] $Name
[int] $Size
[ProjectState] $State
[ProjectAssignee] $Assignee
[datetime] $StartDate
[datetime] $EndDate
[datetime] $DueDate
}
[ExampleProject2]@{
Name = 'Class Property Documentation'
Size = 8
State = 'InProgress'
Assignee = @{
DisplayName = 'Mikey Lombardi'
UserName = 'michaeltlombardi'
}
StartDate = '2023-10-23'
DueDate = '2023-10-27'
}
Name : Class Property Documentation
Size : 8
State : InProgress
Assignee : Mikey Lombardi (michaeltlombardi)
StartDate : 10/23/2023 12:00:00 AM
EndDate : 1/1/0001 12:00:00 AM
DueDate : 10/27/2023 12:00:00 AM
Пример 3. Свойство класса с атрибутом проверки
Класс ExampleProject3 определяет свойство Size как целое число, которое должно быть больше или равно 0 и меньше или равно 16. Он использует атрибут ValidateRange для ограничения значения.
class ExampleProject3 {
[string] $Name
[ValidateRange(0, 16)] [int] $Size
[bool] $Completed
[string] $Assignee
[datetime] $StartDate
[datetime] $EndDate
[datetime] $DueDate
}
$project = [ExampleProject3]::new()
$project
Name :
Size : 0
Completed : False
Assignee :
StartDate : 1/1/0001 12:00:00 AM
EndDate : 1/1/0001 12:00:00 AM
DueDate : 1/1/0001 12:00:00 AM
При создании экземпляра ExampleProject3 размер по умолчанию — 0. При задании свойства значение в допустимом диапазоне обновляется.
$project.Size = 8
$project
Name :
Size : 8
Completed : False
Assignee :
StartDate : 1/1/0001 12:00:00 AM
EndDate : 1/1/0001 12:00:00 AM
DueDate : 1/1/0001 12:00:00 AM
Если для параметра Size задано недопустимое значение за пределами диапазона, PowerShell вызывает исключение, а значение не изменяется.
$project.Size = 32
$project.Size = -1
$project
SetValueInvocationException:
Line |
1 | $project.Size = 32
| ~~~~~~~~~~~~~~~~~~
| Exception setting "Size": "The 32 argument is greater than the
| maximum allowed range of 16. Supply an argument that is less than
| or equal to 16 and then try the command again."
SetValueInvocationException:
Line |
2 | $project.Size = -1
| ~~~~~~~~~~~~~~~~~~
| Exception setting "Size": "The -1 argument is less than the minimum
| allowed range of 0. Supply an argument that is greater than or
| equal to 0 and then try the command again."
Name :
Size : 8
Completed : False
Assignee :
StartDate : 1/1/0001 12:00:00 AM
EndDate : 1/1/0001 12:00:00 AM
DueDate : 1/1/0001 12:00:00 AM
Пример 4. Свойство класса с явным значением по умолчанию
Класс ExampleProject4 по умолчанию использует значение свойства StartDate до текущей даты.
class ExampleProject4 {
[string] $Name
[int] $Size
[bool] $Completed
[string] $Assignee
[datetime] $StartDate = (Get-Date).Date
[datetime] $EndDate
[datetime] $DueDate
}
[ExampleProject4]::new()
[ExampleProject4]::new().StartDate -eq (Get-Date).Date
Name :
Size : 0
Completed : False
Assignee :
StartDate : 10/23/2023 12:00:00 AM
EndDate : 1/1/0001 12:00:00 AM
DueDate : 1/1/0001 12:00:00 AM
True
Пример 5. Скрытое свойство класса
Свойство Guid класса ExampleProject5 имеет ключевое hidden
слово. Свойство Guid не отображается в выходных данных по умолчанию для класса или в списке свойств, возвращаемых Get-Member
.
class ExampleProject5 {
[string] $Name
[int] $Size
[bool] $Completed
[string] $Assignee
[datetime] $StartDate
[datetime] $EndDate
[datetime] $DueDate
hidden [string] $Guid = (New-Guid).Guid
}
$project = [ExampleProject5]::new()
"Project GUID: $($project.Guid)"
$project
$project | Get-Member -MemberType Properties | Format-Table
Project GUID: c72cef84-057c-4649-8940-13490dcf72f0
Name :
Size : 0
Completed : False
Assignee :
StartDate : 1/1/0001 12:00:00 AM
EndDate : 1/1/0001 12:00:00 AM
DueDate : 1/1/0001 12:00:00 AM
TypeName: ExampleProject5
Name MemberType Definition
---- ---------- ----------
Assignee Property string Assignee {get;set;}
Completed Property bool Completed {get;set;}
DueDate Property datetime DueDate {get;set;}
EndDate Property datetime EndDate {get;set;}
Name Property string Name {get;set;}
Size Property int Size {get;set;}
StartDate Property datetime StartDate {get;set;}
Пример 6. Свойство статического класса
Класс ExampleProject6 определяет свойство static Projects в виде списка всех созданных проектов. Конструктор по умолчанию для класса добавляет новый экземпляр в список проектов.
class ExampleProject6 {
[string] $Name
[int] $Size
[bool] $Completed
[string] $Assignee
[datetime] $StartDate
[datetime] $EndDate
[datetime] $DueDate
hidden [string] $Guid = (New-Guid).Guid
static [ExampleProject6[]] $Projects = @()
ExampleProject6() {
[ExampleProject6]::Projects += $this
}
}
"Project Count: $([ExampleProject6]::Projects.Count)"
$project1 = [ExampleProject6]@{ Name = 'Project_1' }
$project2 = [ExampleProject6]@{ Name = 'Project_2' }
[ExampleProject6]::Projects | Select-Object -Property Name, Guid
Project Count: 0
Name Guid
---- ----
Project_1 75e7c8a0-f8d1-433a-a5be-fd7249494694
Project_2 6c501be4-e68c-4df5-8fce-e49dd8366afe
Пример 7. Определение свойства в конструкторе
Класс ExampleProject7 определяет свойство скрипта Duration в конструкторе статических классов с помощью командлета Update-TypeData
. Update-TypeData
Использование или Add-Member
командлет — единственный способ определить расширенные свойства для классов PowerShell.
Свойство Duration возвращает значение, $null
если только свойства StartDate и EndDate не заданы, а StartDate определен как более ранний, чем EndDate.
class ExampleProject7 {
[string] $Name
[int] $Size
[bool] $Completed
[string] $Assignee
[datetime] $StartDate
[datetime] $EndDate
[datetime] $DueDate
static [hashtable[]] $MemberDefinitions = @(
@{
MemberName = 'Duration'
MemberType = 'ScriptProperty'
Value = {
[datetime]$UnsetDate = 0
$StartNotSet = $this.StartDate -eq $UnsetDate
$EndNotSet = $this.EndDate -eq $UnsetDate
$StartAfterEnd = $this.StartDate -gt $this.EndDate
if ($StartNotSet -or $EndNotSet -or $StartAfterEnd) {
return $null
}
return $this.EndDate - $this.StartDate
}
}
)
static ExampleProject7() {
$TypeName = [ExampleProject7].Name
foreach ($Definition in [ExampleProject7]::MemberDefinitions) {
Update-TypeData -TypeName $TypeName @Definition
}
}
ExampleProject7() {}
ExampleProject7([string]$Name) {
$this.Name = $Name
}
}
$Project = [ExampleProject7]::new()
$Project
$null -eq $Project.Duration
Duration :
Name :
Size : 0
Completed : False
Assignee :
StartDate : 1/1/0001 12:00:00 AM
EndDate : 1/1/0001 12:00:00 AM
DueDate : 1/1/0001 12:00:00 AM
True
Представление по умолчанию для экземпляра класса ExampleProject7 включает длительность. Так как свойства StartDate и EndDate не заданы, свойство Duration имеет значение $null
.
$Project.StartDate = '2023-01-01'
$Project.EndDate = '2023-01-08'
$Project
Duration : 7.00:00:00
Name :
Size : 0
Completed : False
Assignee :
StartDate : 1/1/2023 12:00:00 AM
EndDate : 1/8/2023 12:00:00 AM
DueDate : 1/1/0001 12:00:00 AM
При правильном наборе свойств свойство Duration возвращает интервал времени, представляющий время выполнения проекта.
Значения свойств по умолчанию
Каждое свойство класса имеет неявное значение по умолчанию в зависимости от типа свойства.
Если свойство является ссылочным типом, например строкой или объектом, неявное значение по умолчанию.$null
Если свойство является типом значения, например числом, логическим или перечислением, свойство имеет значение по умолчанию в зависимости от типа:
- Числовые типы, такие как целые числа и числа с плавающей запятой, по умолчанию
0
- Логические значения по умолчанию
$false
- Перечисления по умолчанию по умолчанию
0
, даже перечисление не определяет метку для0
.
Дополнительные сведения о значениях по умолчанию в .NET см. в разделе "Значения по умолчанию" типов C# (справочник по C#).
Чтобы определить явное значение по умолчанию для свойства, объявите свойство с назначением значению по умолчанию.
Например, это определение для класса ProjectTask определяет явное значение по умолчанию для свойства Guid, присваивая случайный GUID каждому новому экземпляру.
class ProjectTask {
[string] $Name
[string] $Description
[string] $Guid = (New-Guid).Guid
}
[ProjectTask]::new()
Name Description Guid
---- ----------- ----
aa96350c-358d-465c-96d1-a49949219eec
Скрытые и статические свойства также могут иметь значения по умолчанию.
Скрытые свойства
Свойства класса можно скрыть, объявив их ключевым словом hidden
.
Скрытые свойства класса:
- Не включен в выходные данные по умолчанию для класса.
- Не включен в список членов класса, возвращаемых командлетом
Get-Member
. Чтобы отобразить скрытые свойства сGet-Member
помощью параметра Force, используйте параметр Force . - Не отображается в завершении вкладки или IntelliSense, если только не выполняется завершение в классе, определяющем скрытое свойство.
- Открытые члены класса. К ней можно обращаться и изменять. Скрытие свойства не делает его частным. Он скрывает только свойство, как описано в предыдущих точках.
Дополнительные сведения о ключевом слове hidden
см. в about_Hidden.
Статические свойства
Свойство можно определить как принадлежащее самому классу, а не экземплярам класса, объявив свойство ключевым словом static
. Свойства статического класса:
- Всегда доступны независимо от экземпляра класса.
- Общий доступ ко всем экземплярам класса.
- Всегда доступны.
- Модификаторы. Статические свойства можно обновить. По умолчанию они неизменяемы.
- Динамическая трансляция для всего диапазона сеансов.
Внимание
Статические свойства для классов, определенных в PowerShell, не являются неизменяемыми. Они могут
Свойства производного класса
Если класс является производным от базового класса, он наследует свойства базового класса. Все свойства, определенные в базовом классе, включая скрытые свойства, доступны в производном классе.
Производный класс может переопределить унаследованное свойство, переопределив его в определении класса. Свойство в производном классе использует переопределенный тип и значение по умолчанию, если таковые имеются. Если унаследованное свойство определило значение по умолчанию и переопределенное свойство не имеет, унаследованное свойство не имеет значения по умолчанию.
Если производный класс не переопределяет статическое свойство, доступ к статическому свойству через производный класс обращается к статическому свойству базового класса. Изменение значения свойства через производный класс изменяет значение базового класса. Любой другой производный класс, который не переопределяет статическое свойство, также использует значение свойства в базовом классе. Обновление значения унаследованного статического свойства в классе, который не переопределяет свойство, может иметь непредвиденные последствия для классов, производных от одного базового класса.
В следующем примере показано поведение свойств статического и экземпляра в производных классах.
class BaseClass {
static [string] $StaticProperty = 'Static'
[string] $InstanceProperty = 'Instance'
}
class DerivedClassA : BaseClass {}
class DerivedClassB : BaseClass {}
class DerivedClassC : DerivedClassB {
[string] $InstanceProperty
}
class DerivedClassD : BaseClass {
static [string] $StaticProperty = 'Override'
[string] $InstanceProperty = 'Override'
}
"Base instance => $([BaseClass]::new().InstanceProperty)"
"Derived instance A => $([DerivedClassA]::new().InstanceProperty)"
"Derived instance B => $([DerivedClassB]::new().InstanceProperty)"
"Derived instance C => $([DerivedClassC]::new().InstanceProperty)"
"Derived instance D => $([DerivedClassD]::new().InstanceProperty)"
Base instance => Instance
Derived instance A => Instance
Derived instance B => Instance
Derived instance C =>
Derived instance D => Override
ЭкземплярProperty для DerivedClassC является пустой строкой, так как класс переопределен свойству без задания значения по умолчанию. Для Производного класса значение заключается в Override
том, что класс переопредел свойство с этой строкой в качестве значения по умолчанию.
"Base static => $([BaseClass]::StaticProperty)"
"Derived static A => $([DerivedClassA]::StaticProperty)"
"Derived static B => $([DerivedClassB]::StaticProperty)"
"Derived static C => $([DerivedClassC]::StaticProperty)"
"Derived static D => $([DerivedClassD]::StaticProperty)"
Base static => Static
Derived static A => Static
Derived static B => Static
Derived static C => Static
Derived static D => Override
За исключением производного класса, значение статического свойства для производных классов совпадает с базовым классом, так как они не переопределяют свойство. Это относится даже к производной классификации, которая наследуется от Производного класса, а не непосредственно от BaseClass.
[DerivedClassA]::StaticProperty = 'Updated from A'
"Base static => $([BaseClass]::StaticProperty)"
"Derived static A => $([DerivedClassA]::StaticProperty)"
"Derived static B => $([DerivedClassB]::StaticProperty)"
"Derived static C => $([DerivedClassC]::StaticProperty)"
"Derived static D => $([DerivedClassD]::StaticProperty)"
Base static => Updated from A
Derived static A => Updated from A
Derived static B => Updated from A
Derived static C => Updated from A
Derived static D => Override
При доступе и изменении StaticProperty с помощью DerivedClassA измененное значение влияет на каждый класс, кроме Производного КлассаD.
Дополнительные сведения о наследовании классов, включая полный пример, см . в about_Classes_Inheritance.
Использование атрибутов свойств
PowerShell включает несколько классов атрибутов, которые можно использовать для улучшения сведений о типе данных и проверки данных, назначенных свойству. Атрибуты проверки позволяют проверить, что значения, заданные свойствам, соответствуют определенным требованиям. Проверка активируется момент назначения значения.
Дополнительные сведения о доступных атрибутах см. в about_Functions_Advanced_Parameters.
Определение свойств экземпляра с помощью Update-TypeData
Помимо объявления свойств непосредственно в определении класса, можно определить свойства для экземпляров класса в статической конструкторе с помощью командлета Update-TypeData
.
Используйте этот фрагмент в качестве отправной точки для шаблона. Замените текст заполнителя в угловых скобках по мере необходимости.
class <ClassName> {
static [hashtable[]] $MemberDefinitions = @(
@{
MemberName = '<PropertyName>'
MemberType = '<PropertyType>'
Value = <ValueDefinition>
}
)
static <ClassName>() {
$TypeName = [<ClassName>].Name
foreach ($Definition in [<ClassName>]::MemberDefinitions) {
Update-TypeData -TypeName $TypeName @Definition
}
}
}
Совет
Командлет Add-Member
может добавлять свойства и методы в класс в нестатических конструкторах, но командлет выполняется каждый раз при вызове конструктора. Использование Update-TypeData
в статическом конструкторе гарантирует, что код для добавления членов в класс должен выполняться только один раз в сеансе.
Только добавляйте свойства в класс в нестатических конструкторах, если они не могут быть определены с Update-TypeData
такими свойствами, как только для чтения.
Определение свойств псевдонима
Атрибут Alias не влияет при использовании в объявлении свойства класса. PowerShell использует только этот атрибут для определения псевдонимов для имен командлетов, параметров и функций.
Чтобы определить псевдоним для свойства класса, используйте Update-TypeData
с типом AliasProperty
MemberType.
Например, это определение класса OperablePair определяет два целочисленных свойства x и y с псевдонимами LeftHandSide и RightHandSide соответственно.
class OperablePair {
[int] $x
[int] $y
static [hashtable[]] $MemberDefinitions = @(
@{
MemberType = 'AliasProperty'
MemberName = 'LeftHandSide'
Value = 'x'
}
@{
MemberType = 'AliasProperty'
MemberName = 'RightHandSide'
Value = 'y'
}
)
static OperablePair() {
$TypeName = [OperablePair].Name
foreach ($Definition in [OperablePair]::MemberDefinitions) {
Update-TypeData -TypeName $TypeName @Definition
}
}
OperablePair() {}
OperablePair([int]$x, [int]$y) {
$this.x = $x
$this.y = $y
}
# Math methods for the pair of values
[int] GetSum() { return $this.x + $this.y }
[int] GetProduct() { return $this.x * $this.y }
[int] GetDifference() { return $this.x - $this.y }
[float] GetQuotient() { return $this.x / $this.y }
[int] GetModulus() { return $this.x % $this.y }
}
Определяя псевдонимы, пользователи могут получить доступ к свойствам с помощью любого имени.
$pair = [OperablePair]@{ x = 8 ; RightHandSide = 3 }
"$($pair.x) % $($pair.y) = $($pair.GetModulus())"
$pair.LeftHandSide = 3
$pair.RightHandSide = 2
"$($pair.x) x $($pair.y) = $($pair.GetProduct())"
8 % 3 = 2
3 x 2 = 6
Определение вычисляемых свойств
Чтобы определить свойство, которое ссылается на значения других свойств, используйте командлет с типом Update-TypeData
ScriptProperty
MemberType.
Например, это определение класса «Бюджет» определяет свойства Expenses и Revenues в виде массивов чисел с плавающей запятой. Он использует Update-TypeData
командлет для определения вычисляемых свойств для общих расходов, общих доходов и чистого дохода.
class Budget {
[float[]] $Expenses
[float[]] $Revenues
static [hashtable[]] $MemberDefinitions = @(
@{
MemberType = 'ScriptProperty'
MemberName = 'TotalExpenses'
Value = { ($this.Expenses | Measure-Object -Sum).Sum }
}
@{
MemberType = 'ScriptProperty'
MemberName = 'TotalRevenues'
Value = { ($this.Revenues | Measure-Object -Sum).Sum }
}
@{
MemberType = 'ScriptProperty'
MemberName = 'NetIncome'
Value = { $this.TotalRevenues - $this.TotalExpenses }
}
)
static Budget() {
$TypeName = [Budget].Name
foreach ($Definition in [Budget]::MemberDefinitions) {
Update-TypeData -TypeName $TypeName @Definition
}
}
Budget() {}
Budget($Expenses, $Revenues) {
$this.Expenses = $Expenses
$this.Revenues = $Revenues
}
}
[Budget]::new()
[Budget]@{
Expenses = @(2500, 1931, 3700)
Revenues = @(2400, 2100, 4150)
}
TotalExpenses : 0
TotalRevenues : 0
NetIncome : 0
Expenses :
Revenues :
TotalExpenses : 8131
TotalRevenues : 8650
NetIncome : 519
Expenses : {2500, 1931, 3700}
Revenues : {2400, 2100, 4150}
Определение свойств с помощью пользовательской логики получения и задания
Свойства класса PowerShell не могут определять пользовательскую логику получения и задания напрямую. Вы можете приблизить эту функцию, определив резервное свойство с hidden
ключевым словом и используя Update-TypeData
для определения видимого свойства с пользовательской логикой для получения и настройки значения.
По соглашению определите скрытое имя свойства резервного копирования с префиксом подчеркивания и используйте регистр верблюда. Например, вместо имени TaskCount
имени скрытого свойства _taskCount
резервного копирования.
В этом примере класс ProjectSize определяет скрытое целочисленное свойство с именем _value. Он определяет значение как настраиваемую ScriptProperty
логику для получения и настройки свойства _value . Блок скрипта setter обрабатывает преобразование строкового представления проекта в правильный размер.
class ProjectSize {
hidden [ValidateSet(0, 1, 2, 3)] [int] $_value
static [hashtable[]] $MemberDefinitions = @(
@{
MemberType = 'ScriptProperty'
MemberName = 'Value'
Value = { $this._value } # Getter
SecondValue = { # Setter
$ProposedValue = $args[0]
if ($ProposedValue -is [string]) {
switch ($ProposedValue) {
'Small' { $this._value = 1 ; break }
'Medium' { $this._value = 2 ; break }
'Large' { $this._value = 3 ; break }
default { throw "Unknown size '$ProposedValue'" }
}
} else {
$this._value = $ProposedValue
}
}
}
)
static ProjectSize() {
$TypeName = [ProjectSize].Name
foreach ($Definition in [ProjectSize]::MemberDefinitions) {
Update-TypeData -TypeName $TypeName @Definition
}
}
ProjectSize() {}
ProjectSize([int]$Size) { $this.Value = $Size }
ProjectSize([string]$Size) { $this.Value = $Size }
[string] ToString() {
$Output = switch ($this._value) {
1 { 'Small' }
2 { 'Medium' }
3 { 'Large' }
default { 'Undefined' }
}
return $Output
}
}
Определяя настраиваемый метод получения и задания, можно задать свойство Value как целое число или строку.
$size = [ProjectSize]::new()
"The initial size is: $($size._value), $size"
$size.Value = 1
"The defined size is: $($size._value), $size"
$Size.Value += 1
"The updated size is: $($size._value), $size"
$Size.Value = 'Large'
"The final size is: $($size._value), $size"
The initial size is: 0, Undefined
The defined size is: 1, Small
The updated size is: 2, Medium
The final size is: 3, Large
Ограничения
Свойства класса PowerShell имеют следующие ограничения:
Статические свойства всегда изменяются. Классы PowerShell не могут определять неизменяемые статические свойства.
Обходной путь: нет.
Свойства не могут использовать атрибут ValidateScript , так как аргументы атрибута свойства класса должны быть константами.
Обходное решение. Определите класс, наследующий от типа ValidateArgumentsAttribute , и используйте этот атрибут.
Непосредственно объявленные свойства не могут определять пользовательские реализации получения и задания.
Обходное решение. Определение скрытого свойства и использование
Update-TypeData
для определения видимой логики получения и задания.Свойства не могут использовать атрибут Alias . Атрибут применяется только к параметрам, командлетам и функциям.
Обходное
Update-TypeData
решение. Используйте командлет для определения псевдонимов в конструкторах классов.При преобразовании класса PowerShell в JSON с помощью командлета
ConvertTo-Json
выходные данные JSON включают все скрытые свойства и их значения.Обходной путь: нет
См. также
PowerShell